在c++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这一点,但它给了我奇怪的链接器错误:

class foo
{
    private:
        static int i;
};

int foo::i = 0;

我猜这是因为我不能从类外部初始化一个私有成员。那么最好的方法是什么呢?


当前回答

对于变量:

foo。:

class foo
{
private:
    static int i;
};

foo.cpp:

int foo::i = 0;

这是因为在你的程序中只能有一个foo::i实例。它相当于头文件中的extern int i和源文件中的int i。

对于常量,你可以把值直接放在类声明中:

class foo
{
private:
    static int i;
    const static int a = 42;
};

其他回答

我只是想提一下我第一次遇到这个的时候觉得有点奇怪的东西。

我需要在模板类中初始化一个私有静态数据成员。

在.h或.hpp中,它看起来像这样初始化模板类的静态数据成员:

template<typename T>
Type ClassName<T>::dataMemberName = initialValue;

使用Microsoft编译器[1],不像int型的静态变量也可以在头文件中定义,但在类声明之外,使用Microsoft特定的__declspec(selectany)。

class A
{
    static B b;
}

__declspec(selectany) A::b;

请注意,我并不是说这是好的,我只是说这是可以做到的。

现在,比MSC更多的编译器支持__declspec(selectany)——至少gcc和clang。甚至更多。

int foo::i = 0; 

是初始化变量的正确语法,但它必须放在源文件(.cpp)中,而不是放在头文件中。

因为它是一个静态变量,所以编译器只需要创建它的一个副本。你必须在你的代码中有一行"int foo:i"来告诉编译器把它放在哪里,否则你会得到一个链接错误。如果这是在一个头,你会得到一个拷贝在每个文件,包括头,所以从链接器获得多重定义的符号错误。

对于变量:

foo。:

class foo
{
private:
    static int i;
};

foo.cpp:

int foo::i = 0;

这是因为在你的程序中只能有一个foo::i实例。它相当于头文件中的extern int i和源文件中的int i。

对于常量,你可以把值直接放在类声明中:

class foo
{
private:
    static int i;
    const static int a = 42;
};

定义常量的一种“老派”方法是用枚举替换它们:

class foo
{
    private:
        enum {i = 0}; // default type = int
        enum: int64_t {HUGE = 1000000000000}; // may specify another type
};

这种方法不需要提供定义,并且避免使常量为左值,这可以为您省去一些麻烦,例如当您意外地odr使用它时。