链接器为某些上下文中使用的集成静态常量成员提供错误"undefined symbol"

Linker gives error "undefined symbol" for integral static const members used in certain contexts

本文关键字:成员 常量 静态 错误 symbol undefined 集成 上下文 链接      更新时间:2023-10-16

可能重复:
C++-在类定义中定义静态常量整数成员

注意:关于类似的问题,有几个现存的问题,但我已经审查了其中的许多问题,无法找到解释这种行为的答案:

假设我有如下代码(在文件中)

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整型或const枚举类型,则其在类定义中的声明可以指定const初始值设定项,该初始值设定值设定项应为整型常量表达式。

既然我所做的似乎"在规则范围内",有人能想到对这种奇怪行为的任何可能解释吗?

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

任何见解都将不胜感激。我也可以随时提供更多信息。

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

int const foo::TEST;

(在一个翻译单元中)。如果编译器只访问该值,则可以不定义该对象。除非您需要类型为int,否则可以使用enum,从而避免定义成员:

enum { TEST = 33 };

如果我没有记错的话,标准中要查找的术语是odr使用的

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