Я собираюсь предположить, что вы используете Visual C ++, который имеет довольно ужасное расширение языка, как описано в «Расширения Microsoft для C и C ++» :
Вне класса Определение статических константных (или перечислимых) членов
В соответствии со стандартом (/Za
) вам необходимо создать внеклассное определение для элементов данных. Например,
class CMyClass {
static const int max = 5;
int m_array[max];
}
...
const int CMyClass::max; // out of class definition
При /Ze
определение вне класса является необязательным для статических, константных и константных членов данных. Только интегралы и перечисления, которые являются статическими и константными, могут иметь инициализаторы внутри класса; инициализирующее выражение должно быть константным выражением.
Чтобы избежать ошибок, когда предоставляется определение вне класса (когда определение вне класса предоставляется в файле заголовка, а файл заголовка включен в несколько исходных файлов), вы должны использовать selectany. Например:
__declspec(selectany) const int CMyClass::max = 5;
Флаг /Ze
включен по умолчанию. Вы должны явно использовать флаг /Za
, если не хотите расширений языка.
Код в том виде, в котором он написан, без ошибок компилируется и связывается с использованием g ++ 4.5.2, Clang 3.0 и Visual C ++ 2010 с установленным флагом /Za
.
Удаление определения из файла .cpp решает проблему, если вы хотите скомпилировать с Visual C ++, но тогда оно не будет работать с другими компиляторами (или с /Za
), если вы попытаетесь использовать элемент данных. Для переносимого обходного пути вы можете использовать блок условной компиляции, который проверяет, включены ли расширения:
#ifndef _MSC_EXTENSIONS
const int A::b;
#endif