C++ 静态常量类成员声明

C++ 静态常量类成员声明,c++,gcc,linker,C++,Gcc,Linker,在Foo.h中: class Foo { public: Foo(); static const unsigned int FOOBAR = 10; static const unsigned int BARFOO = 20; private: unsigned int m_FooBar; bool m_Bar; void Bar(); }; 在Foo.cpp中: Foo::Foo() : m_FooBar(FOOBAR), // th

在Foo.h中:

class Foo
{
public:
    Foo();
    static const unsigned int FOOBAR = 10;
    static const unsigned int BARFOO = 20;

private:
    unsigned int m_FooBar;
    bool m_Bar;
    void Bar();
};
在Foo.cpp中:

Foo::Foo()
    : m_FooBar(FOOBAR), // this works
      m_Bar(false)
{
}

void Foo::Bar()
{
    //m_FooBar = m_Bar ? FOOBAR : BARFOO; // linker fails *1
    m_FooBar = FOOBAR; // ok
}
我正在使用GCC4.5.3进行编译。当第*1行未注释时,链接器会失败,有什么原因吗

Foo.o: In function 'Foo::Bar' (name unmangled):
Foo.cpp: undefined reference to `Foo::FOOBAR'
Foo.cpp: undefined reference to `Foo::BARFOO'
使用VC2005、2008、2010和CB2010进行试验。它们都很好地进行了汇编和链接。为什么GCC在这种情况下失败


既然如此,为什么其他流行的编译器没有像GCC那样失败呢?不管怎样,它都是一个bug,无论是对于GCC还是其他流行的编译器。或者有更合理的解释吗?

尝试定义这些成员:

static const unsigned int FOOBAR = 10;
static const unsigned int BARFOO = 20;
在类声明之外

Foo::FOOBAR = 10;
Foo::BARFOO = 20;

形式上,头文件只声明静态常量,并且还必须定义它们(至少在C++03中)。然而,如果你只使用他们的价值观,你通常会侥幸逃脱

在C++11中,这更正式地指定为当static为“使用odr”时需要定义。
*1
行就是一个例子。triadic运算符试图形成对值的引用,而编译器(或链接器)实际上意识到它不能


C++11标准说

9.4.2静态数据成员
§3…
该成员仍应被定义 如果在程序中使用odr(3.2),则在名称空间范围中,并且名称空间范围定义不应 包含初始值设定项


隐马尔可夫模型。。。它在VS2010中编译得很好。@但神秘的问题是关于gcc的。我可以确认链接器错误。可能的副本已经存档。@ZachSaw:从技术上讲,你是对的。根据ISO C++11标准,这不是一个缺陷,因为直到2012年2月标准批准后,对该标准的更改才被纳入工作文件。然而,由于委员会确定这是当前标准中的一个缺陷,因此将其作为bug归档,以确保任何未来版本的gcc Exhibit符合所需的行为(并且因为未来的标准将有这些更正)。但是在c++03中,如果在标头中声明和定义整型静态常量,则整型静态常量是可以的,就像在问题中,如果你只使用他们的价值观,他们是好的。triadic运算符生成对两个值之一的引用,这在未定义它们时是不可能的。如果试图通过引用将其中一个值传递给函数,则会得到类似的效果。那么为什么其他流行的编译器不这样做呢?如果triadic操作符做到了这一点,那么它在VC2010上不也应该失败吗?@Zach-并非所有编译器都严格遵循标准。:-)一些早期的VC版本甚至声称不允许定义@波普森:是的。VC6根本不允许这样!