在类定义中定义静态常量整型成员
我的理解是,C ++允许静态const成员在类中定义,只要它是一个整数types。
那么,为什么下面的代码给我一个链接错误?
#include <algorithm> #include <iostream> class test { public: static const int N = 10; }; int main() { std::cout << test::N << "\n"; std::min(9, test::N); }
我得到的错误是:
test.cpp:(.text+0x130): undefined reference to `test::N' collect2: ld returned 1 exit status
有趣的是,如果我注释掉std :: min的调用,代码编译和链接就好了(即使test :: N也在前一行中引用)。
任何想法是怎么回事?
我的编译器是Linux上的gcc 4.4。
我的理解是,C ++允许静态const成员在类中定义,只要它是一个整数types。
你是正确的。 您可以在类声明中初始化静态常量集成,但这不是一个定义。
有趣的是,如果我注释掉std :: min的调用,代码编译和链接就好了(即使test :: N也在前一行中引用)。
任何想法是怎么回事?
std :: min通过const引用获取其参数。 如果它们的价值,你不会有这个问题,但既然你需要一个参考,你也需要一个定义。
这是章节/诗句:
9.4.2 / 4 – 如果static
数据成员是const
整型或const
枚举types的,则它在类定义中的声明可以指定一个常数初始值设定项 ,它应该是一个整型常量expression式(5.19)。 在这种情况下,成员可以出现在整型常量expression式中。 如果在程序中使用成员,则该成员仍应在名称空间作用域中定义,并且名称空间作用域定义不应包含初始值设定项 。
有关可能的解决方法,请参阅Chu的答案。
Bjarne Stroustrup 在他的C ++ FAQ中的例子表明你是正确的,并且只要你知道地址就只需要一个定义。
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 // ... }
他说: “如果(并且只有)它有一个不符合类的定义,你可以采取静态成员的地址” 。 这表明它会起作用。 也许你最小的函数在幕后调用地址。
另一种方法,无论如何,对于整数types来说,是将常量定义为类中的枚举:
class test { public: enum { N = 10 }; };
不只是int的。 但是你不能在类声明中定义这个值。 如果你有:
class classname { public: static int const N; }
在.h文件中,那么你必须有:
int const classname::N = 10;
在.cpp文件中。
这是解决问题的另一种方法:
std::min(9, int(test::N));
(我认为Crazy Eddie的回答正确地描述了问题存在的原因。)
C ++允许静态const成员在类中定义
不,3.1§2说:
声明是一个定义,除非它声明一个没有指定函数体(8.4)的函数,它包含extern说明符(7.1.1)或者一个联合规范(7.5),既不是初始化函数也不是函数体, 它声明一个静态数据成员在类定义 (9.4)中,它是一个类名声明(9.1),它是一个不透明的枚举声明(7.2),或者是一个typedef声明(7.1.3),一个使用声明(7.3。 3)或使用指令(7.3.4)。
从C ++ 11开始,你可以(和你想)使用:
static constexpr int N = 10;
这不需要您在.cpp文件中定义常量。