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

What does it mean to have an undefined reference to a static member?

我刚刚编写了一个包含一些静态数据成员的类,但现在我在"未定义引用"方面遇到了错误。为什么这个不行?我做错什么了?

(注:这意味着是堆栈溢出的C++FAQ的一个条目。如果你想批评在这个表单中提供一个常见问题解答的想法,那么在meta上发布的开始所有这一切的地方就是这样做的地方。这个问题的答案是在C++聊天室中进行监控的,FAQ的想法一开始就出现了,所以你的答案很可能会被那些想出这个想法的人读到。


要理解这一点,您应该对编译和链接以及声明和定义之间的差异有很好的理解。

考虑以下类别:

1
2
3
4
//In header file
class Example {
    static bool exampleStaticMember;
};

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

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

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

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

特殊情况下,如果静态成员变量是常量整数或枚举类型,则它在类定义中可以有一个初始化器:

1
2
3
4
//In header file
class Example {
    static const int initialised = 15;
};

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

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

像这样初始化的静态成员可以在常量表达式中使用。

模板

对于模板的静态数据成员,情况略有不同。静态成员应与类的其余部分一起在头中定义:

1
2
3
4
5
6
7
8
//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;

这是因为类模板的静态数据成员的一个定义规则存在特定的异常。

静电的其他用途

static关键字应用于不在类范围内的函数和对象时,它可能具有非常不同的含义。

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

当应用于命名空间范围(在任何类或函数定义之外)的对象或函数时,它声明具有内部链接的对象或函数。不赞成对对象使用此用法,因为未命名的命名空间提供了更好的替代方法。


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

1
2
3
4
5
6
7
8
9
10
11
12
// foo.h

class foo {
    static int X;
};


// foo.cpp

#include"foo.h"

int foo::X = 0;