在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
当前回答
您遇到的链接器问题可能是由以下原因引起的:
在头文件中提供类和静态成员定义, 在两个或多个源文件中包含此头文件。
对于那些从c++开始学习的人来说,这是一个常见的问题。静态类成员必须在单个翻译单元中初始化,即在单个源文件中初始化。
不幸的是,静态类成员必须在类体之外初始化。这使得只写头的代码变得复杂,因此,我使用了完全不同的方法。你可以通过静态或非静态类函数来提供你的静态对象,例如:
class Foo
{
// int& getObjectInstance() const {
static int& getObjectInstance() {
static int object;
return object;
}
void func() {
int &object = getValueInstance();
object += 5;
}
};
其他回答
使用Microsoft编译器[1],不像int型的静态变量也可以在头文件中定义,但在类声明之外,使用Microsoft特定的__declspec(selectany)。
class A
{
static B b;
}
__declspec(selectany) A::b;
请注意,我并不是说这是好的,我只是说这是可以做到的。
现在,比MSC更多的编译器支持__declspec(selectany)——至少gcc和clang。甚至更多。
我只是想提一下我第一次遇到这个的时候觉得有点奇怪的东西。
我需要在模板类中初始化一个私有静态数据成员。
在.h或.hpp中,它看起来像这样初始化模板类的静态数据成员:
template<typename T>
Type ClassName<T>::dataMemberName = initialValue;
如果使用头保护,也可以在头文件中包含赋值。我在自己创建的c++库中使用了这种技术。实现相同结果的另一种方法是使用静态方法。例如……
class Foo
{
public:
int GetMyStatic() const
{
return *MyStatic();
}
private:
static int* MyStatic()
{
static int mStatic = 0;
return &mStatic;
}
}
上面的代码有一个“好处”,就是不需要CPP/源文件。同样,这是我在c++库中使用的方法。
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)方法,我们的静态变量就会被初始化。
这与其他注释并不矛盾,实际上它遵循了在全局作用域中初始化变量的相同原则,但是通过使用这个方法,我们使其显式(并且易于看到-理解),而不是将变量的定义挂在那里。
我遵循卡尔的想法。我喜欢它,现在我也在用它。 我稍微改变了一下符号,增加了一些功能
#include <stdio.h>
class Foo
{
public:
int GetMyStaticValue () const { return MyStatic(); }
int & GetMyStaticVar () { return MyStatic(); }
static bool isMyStatic (int & num) { return & num == & MyStatic(); }
private:
static int & MyStatic ()
{
static int mStatic = 7;
return mStatic;
}
};
int main (int, char **)
{
Foo obj;
printf ("mystatic value %d\n", obj.GetMyStaticValue());
obj.GetMyStaticVar () = 3;
printf ("mystatic value %d\n", obj.GetMyStaticValue());
int valMyS = obj.GetMyStaticVar ();
int & iPtr1 = obj.GetMyStaticVar ();
int & iPtr2 = valMyS;
printf ("is my static %d %d\n", Foo::isMyStatic(iPtr1), Foo::isMyStatic(iPtr2));
}
这个输出
mystatic value 7
mystatic value 3
is my static 1 0