Я понимаю, что 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
Интересно, что если я закомментирую вызов std :: min, код компилируется и связывается нормально (хотя test :: N также упоминается в предыдущей строке).
Есть идеи, что происходит?
Мой компилятор - gcc 4.4 для Linux.
c++
static
declaration
definition
HighCommander4
источник
источник
char
вы можете определить его какconstexpr static const char &N = "n"[0];
. Обратите внимание на расширение&
. Я думаю, это работает, потому что буквальные строки определяются автоматически. Хотя меня это немного беспокоит - он может вести себя странно в файле заголовка среди разных единиц перевода, поскольку строка, вероятно, будет иметь несколько разных адресов.inline const int N = 10
, где, насколько мне известно, все еще есть хранилище, определенное компоновщиком. В этом случае можно также использовать встроенное ключевое слово для определения статической переменной внутри теста определения класса.Ответы:
Я понимаю, что C ++ позволяет определять статические константные члены внутри класса, если это целочисленный тип.
Вы вроде как правы. Вы можете инициализировать статические константные интегралы в объявлении класса, но это не определение.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm
Интересно, что если я закомментирую вызов std :: min, код компилируется и связывается нормально (хотя test :: N также упоминается в предыдущей строке).
Есть идеи, что происходит?
std :: min принимает свои параметры по ссылке const. Если бы они брались по значению, у вас не было бы этой проблемы, но, поскольку вам нужна ссылка, вам также нужно определение.
Вот глава / стих:
9.4.2 / 4 - Если элемент
static
данных имеетconst
целочисленный илиconst
перечисляемый тип, его объявление в определении класса может указывать инициализатор константы, который должен быть выражением интегральной константы (5.19). В этом случае член может появляться в целочисленных постоянных выражениях. Член по-прежнему должен быть определен в области пространства имен, если он используется в программе, а определение области пространства имен не должно содержать инициализатор. .См. Ответ Чу для возможного обходного пути.
источник
5
кconst int&
. Так почему бы не рассматривать OPtest::N
как соответствующий литерал?Пример Бьярна Страуструпа в его FAQ по C ++ предполагает, что вы правы, и вам нужно определение, только если вы берете адрес.
Он говорит: «Вы можете взять адрес статического члена, если (и только если) он имеет внеклассовое определение» . Это говорит о том, что это сработало бы иначе. Может быть, ваша функция min как-то за кулисами вызывает адреса.
источник
std::min
принимает свои параметры по ссылке, поэтому требуется определение.template<class K, class V, class C> const typename AE<K,V,C>::KeyContainer::size_type AE<K,V,C>::c7;
KeyContainer - это typedef для std :: vector <K>. Необходимо перечислить все параметры шаблона и написать typename, потому что это зависимый тип. Может, кому-то этот комментарий будет полезен. Однако теперь мне интересно, как экспортировать это в DLL, потому что класс шаблона, конечно, находится в заголовке. Надо ли экспортировать c7 ???Другой способ сделать это, в любом случае для целочисленных типов, - определить константы как перечисления в классе:
источник
Не только int. Но вы не можете определить значение в объявлении класса. Если у вас есть:
в файле .h у вас должно быть:
в файле .cpp.
источник
static const
интегрального члена в определении класса. Но это все еще не определяет этого члена. Подробности см. В ответе Ноя Робертса.Вот еще один способ обойти проблему:
(Я думаю, что ответ Сумасшедшего Эдди правильно описывает, почему существует проблема.)
источник
std::min(9, +test::N);
Начиная с C ++ 11 вы можете использовать:
static constexpr int N = 10;
Теоретически это все еще требует, чтобы вы определяли константу в файле .cpp, но пока вы не берете ее адрес
N
, очень маловероятно, что какая-либо реализация компилятора выдаст ошибку;).источник
Нет, 3.1 §2 говорит:
источник