Мое понимание - то, что C++ позволяет статическим участникам константы быть определенными в классе, пока это - целый тип.
Да ведь затем, следующий код дает мне ошибку компоновщика?
#include <algorithm>
#include <iostream>
class test
{
public:
static const int N = 10;
};
int main()
{
std::cout << test::N << "\n";
std::min(9, test::N);
}
Ошибка, которую я получаю:
test.cpp:(.text+0x130): undefined reference to `test::N'
collect2: ld returned 1 exit status
Интересно, если я комментирую вызов к станд.:: минута, компиляции кода и ссылки очень хорошо (даже при том, что тест:: на N также ссылаются на предыдущей строке).
Какая-либо идея относительно того, что продолжается?
Мой компилятор является gcc 4.4 на Linux.
Насколько я понимаю, C ++ позволяет определять статические константные члены внутри класса, если это целочисленный тип.
Вы вроде правы. Вы можете инициализировать статические константные интегралы в объявлении класса, но это не определение.
Интересно, если бы я закомментируйте вызов std :: min, код компилируется и связывается нормально (хотя test :: N также упоминается в предыдущей строке).
Есть идеи, что происходит?
std :: min принимает свои параметры по константной ссылке. Если бы они брали их по значению, у вас не было бы этой проблемы, но, поскольку вам нужна ссылка, вам также нужно определение.
Вот глава / стих:
9.4.2/4 - Если элемент данных static
имеет целочисленный тип const
или const
], его объявление в определении класса может указывать инициализатор константы , который должен быть выражением интегральной константы (5.19). В этом случае член может появляться в целочисленных постоянных выражениях. Этот член все равно должен быть определен в области пространства имен, если он используется в программе, а определение области пространства имен не должно содержать инициализатор .
См. Ответ Чу, чтобы узнать о возможном обходном пути.
Пример Бьярна Страуструпа в его FAQ по C ++ предполагает, что вы правы, и вам нужно определение, только если вы берете адрес.
class AE {
// ...
public:
static const int c6 = 7;
static const int c7 = 31;
};
const int AE::c7; // definition
int f()
{
const int* p1 = &AE::c6; // error: c6 not an lvalue
const int* p2 = &AE::c7; // ok
// ...
}
Он говорит «Вы можете взять адрес статического члена, если (и только если) он имеет внеклассное определение» . Это говорит о том, что это сработало бы в противном случае. Возможно, ваша функция min как-то за кулисами вызывает адреса.
Другой способ сделать это, в любом случае для целочисленных типов, это определить константы как перечисления в классе:
class test
{
public:
enum { N = 10 };
};
C ++ позволяет определять статические константные члены внутри класса
Нет, пункт 3.1 §2 гласит:
Объявление является определением, если оно не объявляет функцию без указания тела функции (8.4), это содержит спецификатор extern (7.1.1) или спецификацию связывания (7.5) и ни инициализатор, ни тело функции, он объявляет статический член данных в определении класса (9.4), это имя класса объявление (9.1), это объявление непрозрачного перечисления (7.2) или объявление typedef (7.1.3), объявление-использование (7.3.3) или директива-использование (7.3.4).
Не только int. Но вы не можете определить значение в объявлении класса. Если у вас есть:
class classname
{
public:
static int const N;
}
в файле .h, тогда вы должны иметь:
int const classname::N = 10;
в файле .cpp.