静态常量类成员声明

Zac*_*Saw 7 c++ linker gcc

在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();
};
Run Code Online (Sandbox Code Playgroud)

在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
}
Run Code Online (Sandbox Code Playgroud)

我正在使用GCC 4.5.3进行编译.当取消注释第*行时,链接器会失败的原因是什么?

Foo.o: In function 'Foo::Bar' (name unmangled):
Foo.cpp: undefined reference to `Foo::FOOBAR'
Foo.cpp: undefined reference to `Foo::BARFOO'
Run Code Online (Sandbox Code Playgroud)

试过VC2005,2008,2010和CB2010.他们都编译和链接很好.为什么GCC在这种情况下会失败?

鉴于这里答案,为什么其他流行的编译器不像GCC那样失败?无论如何,它必须是一个错误,无论是对于GCC还是其他流行的编译器.还是有更合理的解释?

Bo *_*son 4

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

\n\n

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

\n\n
\n\n

C++11 标准说

\n\n
\n

9.4.2 静态数据成员
\n \xc2\xa73...
\n 如果在程序中以 odr 使用(3.2),则该成员仍应在命名空间作用域中定义,并且命名空间作用域定义不应\n包含一个初始值设定项

\n
\n