对静态成员有一个未定义的引用是什么意思?
我刚刚写了一些静态数据成员的类,但现在我得到关于“未定义的引用”的错误。 为什么这不工作? 我究竟做错了什么?
(注意:这是一个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;