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 在这种情况下会失败?

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

4

2 回答 2

4

形式上,头文件只声明静态常量,它们也必须被定义(至少在 C++03 中)。但是,如果您只使用它们的值,您通常会侥幸逃脱。

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


C++11 标准说

9.4.2 静态数据成员
§3...
如果该成员在程序中被 odr-used (3.2) 使用,则该成员仍应在命名空间范围内定义,并且命名空间范围定义不应包含初始化程序

于 2012-09-19T06:43:59.507 回答
0

尝试定义这些成员:

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

在类声明之外。

Foo::FOOBAR = 10;
Foo::BARFOO = 20;
于 2012-09-19T06:43:39.833 回答