对静态成员有一个未定义的引用是什么意思?

我刚刚写了一些静态数据成员的类,但现在我得到关于“未定义的引用”的错误。 为什么这不工作? 我究竟做错了什么?

(注意:这是一个Stack Overflow的C ++常见问题解答的入口,如果你想批评在这个表单中提供FAQ的想法,那么在这个开始所有这些的meta上的贴子将是这个地方的答案。那个问题在C ++聊天室中进行监控,常见问题解决scheme首先出现,所以你的答案很可能会被那些提出这个想法的人阅读)。

为了理解这一点,你应该对编译和链接以及声明和定义之间的区别有很好的理解。


考虑以下课程:

//In header file class Example { static bool exampleStaticMember; }; 

这里, exampleStaticMember是声明的但没有定义。 这意味着如果使用exampleStaticMember的方式,它必须有一个地址,那么必须有一个单独的定义。 通常,类定义中的静态数据成员的声明不是该成员的定义。

所需的声明通常放在包含该类成员的其他定义的cpp文件中。 它必须和类定义在同一个命名空间中。 定义通常如下所示:

 //In source file: //This may optionally have an initialiser (eg "= true") bool Example::exampleStaticMember; 

这个定义可以放在任何cpp文件中,但不能放在头文件中,因为这可能会破坏一个定义规则 。

作为一个特殊情况,如果静态成员variables是一个const整型或枚举types,那么它可以在类定义中有一个初始化器:

 //In header file class Example { static const int initialised = 15; }; 

在这种情况下,cpp文件中的定义仍然是必需的,但是不允许有一个初始化程序:

 //In source file //Note: no initialiser! const int Example::initialised; 

已经被初始化的静态成员可以在常量expression式中使用。

模板

对于模板的静态数据成员,情况稍有不同。 静态成员应该和其他的类一起在头文件中定义:

 //In header file template<typename T> class Example { static int exampleInt; static T exampleT; } template<typename T> int Example<T>::exampleInt; template<typename T> T Example<T>::exampleT; 

这是有效的,因为对于类模板的静态数据成员,One Definition Rule存在特定的例外。

其他用途的静态

static关键字应用于不在类作用域中的函数和对象时,它可以具有非常不同的含义。

当应用于函数作用域中的对象时,它将声明一个对象,该对象在函数的第一次执行中被初始化,并随后在函数调用之间保持其值。

当应用于命名空间范围(任何类或函数定义之外)的对象或函数时,它将声明具有内部链接的对象或函数。 这个用法在对象上已经被弃用了,因为unnamed-namespace提供了一个更好的select。

您必须在.cpp文件中实例化标头中定义的静态成员。 例如:

 // foo.h class foo { static int X; }; // foo.cpp #include "foo.h" int foo::X = 0;