链接器为在某些上下文中使用的整数静态const成员提供错误“未定义符号”

时间:2012-11-15 01:42:23

标签: c++ linker initialization standards static-members

  

可能重复:
  C++ - defining static const integer members in class definition

注意:有几个现存的问题是类似的问题,但我已经审查了很多问题,但找不到解释这种行为的答案:

说我有以下代码(在标题文件中)

class Foo {
    static const int TEST = 33;

    public:
    void willItWork(void) {
        printf("%d", std::max(TEST, 75));  // embedded platform, no streams
    }
};

int main(void) {
    Foo tester;
    tester.willItWork();
}

这将编译,但不会链接。我收到链接器错误

  

错误:L6218E:未定义的符号Foo :: TEST(来自foo.o)。

似乎只是将值传递给外部函数会导致问题。在类中的普通表达式或函数中使用TEST可以正常工作。如果我改为将willItWork()写为

void willItWork(void) {
    int diff = TEST - 23;
    printf("%d", diff);
}

没有错误。

我发现另一个引用C ++标准的问题(第9.4.2节):

  

如果静态数据成员是const integer或const枚举类型,则它在类定义中的声明可以指定一个const-initializer,它应该是一个整数常量表达式。

由于我所做的似乎是“在规则范围内”,任何人都可以想到对这种奇怪行为的任何可能的解释吗?

我在ideone上尝试了类似的代码并且没有问题(但是,我无法模仿确切的结构,即使用头文件)。这是否意味着我使用的链接器不完全符合此处的标准?

非常感谢任何见解。我也可以随时提供更多信息。

2 个答案:

答案 0 :(得分:4)

如果编译器认为它需要static成员变量的地址,例如,在某个时刻将变量绑定到引用时,它将创建相应的未定义符号,并且您必须定义该成员:

int const foo::TEST;

(在一个翻译单元中)。如果编译器只访问该值,则可以在不定义对象的情况下逃脱。除非您需要类型为int,否则您可以使用enum代替,并且无需定义成员:

enum { TEST = 33 };

如果我没记错的话,要查找的标准中的术语是 odr-used

答案 1 :(得分:3)

std::max通过引用而非值来获取其参数。将引用绑定到静态const需要一个实际的对象,而不仅仅是值。