2012-09-19 51 views
7

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 
} 

我与GCC 4.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在这种情况下失败?

鉴于answer here,为什么其他流行的编译器不像GCC那样失败?无论如何,它必须是一个bug,无论是GCC还是其他流行的编译器。还是有更合理的解释?

+3

嗯...它在VS2010编译得很好。 – Mysticial

+0

编译和链接CB2010和VS2005 –

+1

@Mysticial问题是关于gcc,但。我可以确认链接器错误。 –

回答

4

形式上,头只声明静态常量,他们也必须定义(至少在C++ 03中)。但是,如果你只使用他们的价值观,你通常会摆脱这种困境。

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


的C++ 11标准说

9.4.2静态数据成员
§3...
人员应仍然在如果它命名空间范围来限定 在程序中被使用(3.2),名称空间范围定义不应该包含初始化程序

+0

但在C++中03如果声明并在头文件中定义了整数静态常量,就像在问题 –

+0

中一样,如果您只是使用它们的值,那么它们都很好。三元运算符产生对两个值中的一个的引用,当它们未被定义时这是不可能的。如果您尝试通过引用某个函数来传递其中一个值,您会得到类似的效果。 –

+0

那么为什么其他流行的编译器不这样做呢?如果三元操作员这样做,它不应该在VC2010上失败吗? –

0

尝试确定这些成员:

static const unsigned int FOOBAR = 10; 
static const unsigned int BARFOO = 20; 

外班宣言。

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