使用静态变量和模板

Nav*_*een 18 c++ static templates visual-c++-6

我有一个像这样的头文件中定义的模板类.这里我也定义了一个静态变量:

#ifndef TEST1_H_
#define TEST1_H_

void f1();

static int count;

template <class T>
class MyClass
{
public:

    void f()
    {
        ++count;
    }


};

#endif
Run Code Online (Sandbox Code Playgroud)

我已经在不同的cpp文件中定义了main()函数,如下所示:

int main(int argc, char* argv[])
{
    MyClass<int> a;
    a.f();
    f1();

    cout<<"Main:" << count << "\n";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在不同的cpp文件中实现了函数f1(),如下所示:

void f1()
{
    MyClass<int> a;
    a.f();

    cout<<"F1: " <<count <<"\n";
}
Run Code Online (Sandbox Code Playgroud)

当我用VC6编译它时,输出为"F1:0 Main:2".这怎么可能?另外,一般情况下,如果我想将静态变量与模板一起使用,我应该如何处理?

Tod*_*lin 23

您获得了同一个变量的两个副本,因为您已在头文件中声明了一个静态变量.当你以static这种方式声明一个全局变量时,你会说它是编译单元(.o文件)的本地变量.由于您在两个编译单元中包含标头,因此您将获得两个副本count.

我认为你真正想要的是一个与模板类的每个实例相关联的静态模板成员变量.它看起来像这样:

template <class T>
class MyClass
{
    // static member declaration
    static int count;
    ...
};

// static member definition
template<class T> int MyClass<T>::count = 0;
Run Code Online (Sandbox Code Playgroud)

这将为您计算模板的每个实例化.也就是说,你就会有一个数MyClass<int>,MyClass<foo>,MyClass<bar>,等 f1()现在看起来是这样的:

void f1() {
    MyClass<int> a;
    a.f();

    cout<<"F1: " << MyClass<int>::count <<"\n";
}
Run Code Online (Sandbox Code Playgroud)

如果要对MyClass的所有实例化进行计数(无论其模板参数如何),都需要使用全局变量.

但是,您可能不希望直接使用全局变量,因为在初始化之前存在使用它的风险.你可以通过创建一个返回对你的计数的引用的全局静态方法来解决这个问题:

int& my_count() {
    static int count = 0;
    return count;
}
Run Code Online (Sandbox Code Playgroud)

然后从你的类中访问它,如下所示:

void f() {
    ++my_count();
}
Run Code Online (Sandbox Code Playgroud)

这将确保计数在使用之前被初始化,无论您从哪个编译单元访问它.有关更多详细信息,请参阅有关静态初始化顺序C++ FAQ.