Defining static const integer members in class definition
我的理解是C++允许静态const成员在一个类中定义,只要它是整数类型。
那么,为什么下面的代码会给我一个链接器错误?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include #include <iostream> class test { public: static const int N = 10; }; int main() { std::cout << test::N <<" "; std::min(9, test::N); } |
我得到的错误是:
1 2 | test.cpp:(.text+0x130): undefined reference to `test::N' collect2: ld returned 1 exit status |
有趣的是,如果我注释掉对std::min的调用,代码编译和链接就很好了(即使在前一行中也引用了test::n)。
知道发生了什么事吗?
我的编译器是Linux上的GCC4.4。
我的理解是C++允许静态const成员在一个类中定义,只要它是整数类型。
你是对的。允许在类声明中初始化静态常量积分,但这不是定义。
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?主题=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm
有趣的是,如果我注释掉对std::min的调用,代码编译和链接就很好了(即使在前一行中也引用了test::n)。
知道发生了什么事吗?
std::min通过常量引用获取其参数。如果按价值计算,你就不会有这个问题,但是因为你需要一个参考,你也需要一个定义。
以下是章节:
9.4.2/4-如果
关于可能的解决办法,请参阅朱棣文的答案。
Bjarne Stroustrup在他的C++ FAQ中的例子表明你是正确的,只需要一个定义,如果你把地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class AE { // ... public: static const int c6 = 7; static const int c7 = 31; }; const int AE::c7; // definition int f() { const int* p1 = &AE::c6; // error: c6 not an lvalue const int* p2 = &AE::c7; // ok // ... } |
他说:"如果静态成员的地址有类外定义(并且只有在这样的情况下),您才能获取该地址。"这表明它在其他方面也会起作用。也许您的min函数会在后台以某种方式调用地址。
对于整数类型,另一种方法是将常量定义为类中的枚举:
1 2 3 4 5 | class test { public: enum { N = 10 }; }; |
不仅是in t的,而且不能在类声明中定义值。如果你有:
1 2 3 4 5 | class classname { public: static int const N; } |
在.h文件中,您必须具有:
1 | int const classname::N = 10; |
在.cpp文件中。
解决这个问题的另一种方法是:
1 | std::min(9, int(test::N)); |
(我认为疯狂埃迪的回答正确地描述了问题存在的原因。)
至于C++ 11,你可以使用:
理论上,这仍然要求您在.cpp文件中定义常量,但只要不使用EDOCX1的地址(4),任何编译器实现都不太可能产生错误;)。
C++ allows static const members to be defined inside a class
不,3.1第2节说:
A declaration is a definition unless it declares a function without specifying the function's body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a functionbody, it declares a static data member in a class definition (9.4), it is a class name declaration (9.1), it is an opaque-enum-declaration (7.2), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).