在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?
当前回答
定义常量的一种“老派”方法是用枚举替换它们:
class foo
{
private:
enum {i = 0}; // default type = int
enum: int64_t {HUGE = 1000000000000}; // may specify another type
};
这种方法不需要提供定义,并且避免使常量为左值,这可以为您省去一些麻烦,例如当您意外地odr使用它时。
其他回答
如果使用头保护,也可以在头文件中包含赋值。我在自己创建的c++库中使用了这种技术。实现相同结果的另一种方法是使用静态方法。例如……
class Foo
{
public:
int GetMyStatic() const
{
return *MyStatic();
}
private:
static int* MyStatic()
{
static int mStatic = 0;
return &mStatic;
}
}
上面的代码有一个“好处”,就是不需要CPP/源文件。同样,这是我在c++库中使用的方法。
从c++ 17开始,静态成员可以在头文件中用inline关键字定义。
http://en.cppreference.com/w/cpp/language/static
静态数据成员可以内联声明。内联静态数据成员可以在类定义中定义,并且可以指定默认成员初始化式。它不需要一个类外定义:
struct X
{
inline static int n = 1;
};
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)方法,我们的静态变量就会被初始化。
这与其他注释并不矛盾,实际上它遵循了在全局作用域中初始化变量的相同原则,但是通过使用这个方法,我们使其显式(并且易于看到-理解),而不是将变量的定义挂在那里。
定义常量的一种“老派”方法是用枚举替换它们:
class foo
{
private:
enum {i = 0}; // default type = int
enum: int64_t {HUGE = 1000000000000}; // may specify another type
};
这种方法不需要提供定义,并且避免使常量为左值,这可以为您省去一些麻烦,例如当您意外地odr使用它时。
如果你想初始化一些复合类型(f.e. string),你可以这样做:
class SomeClass {
static std::list<string> _list;
public:
static const std::list<string>& getList() {
struct Initializer {
Initializer() {
// Here you may want to put mutex
_list.push_back("FIRST");
_list.push_back("SECOND");
....
}
}
static Initializer ListInitializationGuard;
return _list;
}
};
由于ListInitializationGuard是SomeClass::getList()方法中的一个静态变量,它将只被构造一次,这意味着构造函数被调用一次。这将初始化_list变量为你需要的值。任何后续对getList的调用都将返回已经初始化的_list对象。
当然,您必须始终通过调用getList()方法访问_list对象。