Static const в классе С++: undefined ссылка
У меня есть класс для локального использования (т.е. его совпадение - это только файл С++, в котором он определен)
class A {
public:
static const int MY_CONST = 5;
};
void fun( int b ) {
int j = A::MY_CONST; // no problem
int k = std::min<int>( A::MY_CONST, b ); // link error:
// undefined reference to `A::MY_CONST`
}
Весь код находится в том же файле С++. При компиляции с использованием VS на окнах проблем нет.
Однако при компиляции в Linux я получаю ошибку undefined reference
только для второго оператора.
Любые предложения?
Ответы
Ответ 1
std::min<int>
аргументы равны const int&
(а не только int
), то есть ссылки на int
. И вы не можете передать ссылку на A::MY_CONST
, потому что она не определена (только объявлена).
Укажите определение в файле .cpp
вне класса:
class A {
public:
static const int MY_CONST = 5; // declaration
};
const int A::MY_CONST; // definition (no value needed)
Ответ 2
// initialize static constants outside the class
class A {
public:
static const int MY_CONST;
};
const int A::MY_CONST = 5;
void fun( int b ) {
int j = A::MY_CONST; // no problem
int k = std::min<int>( A::MY_CONST, b ); // link error:
// undefined reference to `A::MY_CONST`
}
Ответ 3
Чтобы объяснить, что происходит здесь:
Вы объявили static const
integer внутри класса, эта "функция" здесь, чтобы иметь возможность использовать его как постоянное выражение, т.е. для локального размера массива, несимметричных параметров шаблона и т.д. Если компилятор хочет использовать это константное выражение, он должен уметь видеть это значение в этой единицы перевода.
9,5/3
Если постоянный элемент статистических данных со стабилизатором константы является интегральным или перечисляемым, его объявление в классе определение может указывать логический или равный-инициализатор, в котором каждое предложение-инициализатор, являющееся выражением присваивания, является постоянным выражением (5.19). Статический член данных типа literal может быть объявлен в определение класса со спецификацией constexpr; если это так, в его декларации указывается логический или равный-инициализатор в котором каждое предложение-инициализатор, являющееся выражением-присваиванием, является постоянным выражением. [Примечание: В обоих эти случаи, член может появляться в постоянных выражениях. - end note] Участник должен быть определен в области пространства имен, если он используется в качестве (3.2) в программе, а определение области пространства имен не должно содержат инициализатор.
odr-used означает формирование ссылки на эту переменную или ее адрес.
std::min
принимает значения параметров по ссылке, поэтому они используются как odr.
Решение:
Определите это!
class A
{
static const int a = 5;
};
const int A::a; //definition, shall not contain initializer
Ответ 4
У меня очень странная ситуация.
template<class T> class Strange {
public:
static const char gapchar='-';
};
template<class T> void Strange<T> method1 {
char tmp = gapchar;
}
template<class T> void Strange<T> method2 {
char tmp = gapchar;
}
Я включаю класс выше, он работает уже несколько лет.
Я добавил другой метод, по существу, одну и ту же подпись и просто прочитав пробел.
Я получил ошибку undefined только для третьего метода, даже я использую все три метода.
Затем я изменил способ инициализации статической переменной
не инициализируется в определении класса:
static const char gapchar;
template<class T> const char Strange<T>::gapchar='-';
Это решило проблему. Я не мог понять, почему старый способ
инициализация int или char типа (допускаются только два типа) внутри класса
раздел определения перестает работать только для одного из методов, но не для других.
Ответ 5
Вы также можете сохранить значение const в локальной переменной.
class A {
public:
static const int MY_CONST = 5;
};
void fun( int b ) {
int j = A::MY_CONST; // no problem
int k = std::min<int>( A::MY_CONST, b ); // link error: undefined reference to 'A::MY_CONST'
int l = std::min<int>( j, b); // works
}