在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
当前回答
set_default()方法怎么样?
class foo
{
public:
static void set_default(int);
private:
static int i;
};
void foo::set_default(int x) {
i = x;
}
我们只需要使用set_default(int x)方法,我们的静态变量就会被初始化。
这与其他注释并不矛盾,实际上它遵循了在全局作用域中初始化变量的相同原则,但是通过使用这个方法,我们使其显式(并且易于看到-理解),而不是将变量的定义挂在那里。
其他回答
您遇到的链接器问题可能是由以下原因引起的:
在头文件中提供类和静态成员定义, 在两个或多个源文件中包含此头文件。
对于那些从c++开始学习的人来说,这是一个常见的问题。静态类成员必须在单个翻译单元中初始化,即在单个源文件中初始化。
不幸的是,静态类成员必须在类体之外初始化。这使得只写头的代码变得复杂,因此,我使用了完全不同的方法。你可以通过静态或非静态类函数来提供你的静态对象,例如:
class Foo
{
// int& getObjectInstance() const {
static int& getObjectInstance() {
static int object;
return object;
}
void func() {
int &object = getValueInstance();
object += 5;
}
};
我只是想提一下我第一次遇到这个的时候觉得有点奇怪的东西。
我需要在模板类中初始化一个私有静态数据成员。
在.h或.hpp中,它看起来像这样初始化模板类的静态数据成员:
template<typename T>
Type ClassName<T>::dataMemberName = initialValue;
对于这个问题的未来观众,我想指出您应该避免monkey0506所建议的内容。
头文件用于声明。
对于每个直接或间接包含头文件的.cpp文件,头文件将被编译一次,并且在main()之前在程序初始化时运行任何函数之外的代码。
通过输入:foo::i = VALUE;对于每个.cpp文件,foo:i将被赋值value(不管它是什么),并且这些赋值将以不确定的顺序(由链接器决定)在main()运行之前发生。
如果我们在其中一个。cpp文件中#define VALUE为不同的数字会怎样?它将编译良好,我们将无法知道哪个胜出,直到我们运行程序。
永远不要将执行的代码放入头文件中,这与您永远不要#include .cpp文件的原因相同。
Include守卫(我同意你应该经常使用)保护你不受一些不同情况的影响:在编译一个.cpp文件时,同一个头文件被间接地多次# Include。
也在privatstatic .cpp文件中工作:
#include <iostream>
using namespace std;
class A
{
private:
static int v;
};
int A::v = 10; // possible initializing
int main()
{
A a;
//cout << A::v << endl; // no access because of private scope
return 0;
}
// g++ privateStatic.cpp -o privateStatic && ./privateStatic
int foo::i = 0;
是初始化变量的正确语法,但它必须放在源文件(.cpp)中,而不是放在头文件中。
因为它是一个静态变量,所以编译器只需要创建它的一个副本。你必须在你的代码中有一行"int foo:i"来告诉编译器把它放在哪里,否则你会得到一个链接错误。如果这是在一个头,你会得到一个拷贝在每个文件,包括头,所以从链接器获得多重定义的符号错误。