我有以下代码(简化),它在gcc中编译很好,但在VS中出错:
// main.cpp
#include "test.h"
int main() {
return 0;
}
// test.h
#pragma once
class Test {
static const int TEST = 3;
};
// test.cpp
#include "test.h"
const int Test::TEST;
错误:
main.obj : error LNK2005: "private: static int const Test::TEST" (?TEST@Test@@0HB) already defined in test.obj
是VS错误还是gcc错误地允许我明确定义静态const成员?
更新:在C++ Standard(9.4.2.3)中找到了这一点:
如果非易失性const静态数据成员是整数或枚举类型,则其在类中声明 definition可以指定一个大括号或者相等的初始化程序,其中作为赋值表达式的每个initializer子句都是一个常量表达式(5.20)。可以在。中声明文字类型的静态数据成员 使用constexpr说明符的类定义;如果是这样,其声明应指定一个支撑或等于初始化器 其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [注意:两者都有 在这些情况下,成员可能出现在常量表达式中。 - 尾注] 仍然要定义成员 如果在程序中使用odr-used(3.2)并且命名空间作用域定义不在,则在命名空间作用域中 包含初始化程序。
更新#2:找到了bug report,声称它已在下一个主要版本中修复。
答案 0 :(得分:3)
正如你所说的那样是MSVC bug。 该代码在Visual Studio 2015 RC中使用默认项目选项进行编译和运行。
编译器认为" static const int TEST = 3;"和" const int Test :: TEST;"是同一个变量的两个不同定义。要在您的版本中修复此问题,您可以尝试在.cpp文件中设置静态变量值:
// test.h
#pragma once
class Test {
static const int TEST;
};
// test.cpp
#include "test.h"
const int Test::TEST = 3;
答案 1 :(得分:1)
启用Microsoft Extensions to C and C++后,编译器会自动生成类外定义。有些编译器版本可能有错误并且即使您手动定义它也会执行此自动定义(例如,在编写可移植代码时)。
您可以禁用扩展程序,也可以检查_MSC_EXTENSIONS宏。它是在设置/ Ze选项时定义的。例如:
#ifndef _MSC_EXTENSIONS
const int MyClass::MyStaticMember;
#endif