Определение статических целочисленных членов const в определении класса
Я понимаю, что C++ позволяет определять статические члены const внутри класса, если это целочисленный тип.
почему тогда следующий код дает мне ошибку линкера?
#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
интересно, что если я закомментирую вызов std::min, код компилируется и ссылки просто отлично (хотя test:: N также упоминается в предыдущей строке).
любая идея о том, что происходит дальше?
мой компилятор gcc 4.4 на Linux.
7 ответов:
Я понимаю, что C++ позволяет определять статические члены const внутри класса, если это целочисленный тип.
вы вроде как правы. Вы можете инициализировать статические интегралы const в объявлении класса, но это не определение.
интересно, если я закомментируйте вызов std::min, код компилируется и ссылки просто отлично (хотя test:: N также упоминается в предыдущей строке).
есть идеи относительно того, что происходит?
std:: min принимает свои параметры ссылкой const. Если бы он взял их по значению, у вас не было бы этой проблемы, но поскольку вам нужна ссылка, Вам также нужно определение.
вот глава / стих:
9.4.2/4 - если a
static
элемент данных имеетconst
Интеграл илиconst
тип перечисления, его объявление в определении класса может указывать константы-инициализатора которое должно быть интегральным постоянным выражением (5.19). В этом случае член может отображаться в интегральных константных выражениях. Элемент все равно должен быть определен в области пространства имен, если он используется в программе, и определение области пространства имен не должно содержать инициализатор.см. ответ Чу для возможного обходного пути.
пример Бьярне Страуструпа в его c++ FAQ предполагает, что вы правы, и только нужно определение, если вы берете адрес.
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 }; };
не только int'ам. Но вы не можете определить значение в объявлении класса. Если у вас есть:
class classname { public: static int const N; }
in the .H-файл, то вы должны иметь:
int const classname::N = 10;
in the .файл cpp.
вот еще один способ обойти проблему:
std::min(9, int(test::N));
(Я думаю, что ответ сумасшедшего Эдди правильно описывает, почему проблема существует.)
C++ позволяет определять статические члены const внутри класса
нет, 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).