在类定义中定义静态常量整型成员

我的理解是,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。

你是正确的。 您可以在类声明中初始化静态常量集成,但这不是一个定义。

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

有趣的是,如果我注释掉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文件中定义常量。