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

C++ 对静态成员具有未定义的引用意味着什么?,c++,c++-faq,C++,C++ Faq,我刚刚编写了一个包含一些静态数据成员的类,但是现在我遇到了关于未定义引用的错误。为什么这样不行?我做错了什么 注:这意味着是[堆栈溢出的C++ FAQ ]的条目https://stackoverflow.com/questions/tagged/c++-常见问题。如果你想批评在这个表单中提供FAQ的想法,那么[在meta上发布这一切]https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag 就是这样

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

注:这意味着是[堆栈溢出的C++ FAQ ]的条目https://stackoverflow.com/questions/tagged/c++-常见问题。如果你想批评在这个表单中提供FAQ的想法,那么[在meta上发布这一切]https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag 就是这样做的地方。该问题的答案在[C++聊天室]中监控https://chat.stackoverflow.com/rooms/10/c-lounge,这是常见问题解答的最初想法,因此您的答案很可能会被提出此想法的人阅读_
您必须实例化在.cpp文件的头中定义的静态成员。例如:

// foo.h

class foo {
    static int X;
};


// foo.cpp

#include "foo.h"

int foo::X = 0;

要理解这一点,你应该很好地理解,以及两者之间的区别

考虑以下类别:

//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文件中,但不应该放在类的头中,因为这可能会破坏cpp文件


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

//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关键字应用于不在类范围内的函数和对象时,它可能具有非常不同的含义

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


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

作为一种特殊情况,如果静态成员变量是常量整型或枚举类型,则它可以在类定义中具有初始化器。你是说这里的类声明吗?@SamGoldberg:不是-如果我说的是声明,那么我指的是转发声明,例如class-Example;。从定义上讲,我指的是声明类成员的代码。是的,这些成员本身可以在类定义之外定义,但这在这里并不重要。