对静态成员的未定义引用意味着什么?

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

提问人:Mankarse 提问时间:8/17/2011 最后编辑:CommunityMankarse 更新时间:8/17/2011 访问量:10090

问:

我刚刚编写了一个包含一些静态数据成员的类,但现在我收到了有关“未定义引用”的错误。为什么这不起作用?我做错了什么?

_(注意:这是 [Stack Overflow 的C++常见问题解答](https://stackoverflow.com/questions/tagged/c++-faq) 的条目。如果你想批评以这种形式提供常见问题解答的想法,那么[在开始这一切的元上的帖子](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag)将是这样做的地方。该问题的答案在[C++聊天室](https://chat.stackoverflow.com/rooms/10/c-lounge)中受到监控,FAQ的想法最初是从那里开始的,所以你的答案很可能会被提出这个想法的人阅读。_
C C++-常见问题

评论

0赞 PlasmaHH 8/17/2011
parashift.com/c++-faq-lite/ctors.html#faq-10.12

答:

5赞 Constantinius 8/17/2011 #1

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

// foo.h

class foo {
    static int X;
};


// foo.cpp

#include "foo.h"

int foo::X = 0;
30赞 Mankarse 8/17/2011 #2

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


请考虑以下类:

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

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

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

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

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

作为特殊情况,如果静态成员变量是 const 整型或枚举类型,则它可以在类定义中具有初始值设定项:

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

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

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

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

模板

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

//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

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

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

评论

0赞 Sam Goldberg 8/7/2013
“作为一种特殊情况,如果静态成员变量是常量整型或枚举类型,那么它可以在类定义中有一个初始值设定项”。你是说这里的类声明吗?
0赞 Mankarse 8/7/2013
@SamGoldberg:不,如果我说的是声明,那么我指的是正向声明(例如)。根据定义,我指的是声明类成员的代码。 (是的,这些成员本身可以在类定义之外定义,但这在这里并不重要)。class Example;