C ++未引用类的静态变量

时间:2013-07-08 14:11:36

标签: c++ templates static

在以下程序中打印“此处”:

#include <iostream>
class Base
{
  static bool temp;
  static bool initTemp()
  {std::cout<<"Here\n";return true;}
};

bool Base::temp = Base::initTemp();

class Derived : public Base
{};

int main() {int a;std::cin>>a;}

在以下程序中,“此处”未打印:

#include <iostream>
template <class T>
class Base
{
  static bool temp;
  static bool initTemp()
  {std::cout<<"Here\n";return true;}
};

template <class T>
bool Base<T>::temp = Base<T>::initTemp();

class Derived : public Base<int>
{};

int main() {int a;std::cin>>a;}

在这两种情况下,Base都不会被引用。唯一的区别是在第二种情况下它是一个模板类。谁能向我解释为什么会出现这种情况。我正在使用VS 2012。

3 个答案:

答案 0 :(得分:6)

  

在这两种情况下,Base都不会被引用。

这正是您没有看到任何标准输出打印的原因。

除非使用该数据成员,否则不会实例化类模板的静态数据成员的定义;与成员函数一样,类模板的静态数据成员的定义将按需实例化

这在C ++ 11标准的第14.7.1 / 1段中有详细说明:

  

[...]类模板特化的隐式实例化会导致隐式   类成员函数的声明的实例化,但不是定义或默认参数的实例化,   成员类,作用域成员枚举,静态数据成员和成员模板。 [...]

由于您的客户端代码从不引用Base<>::temp,因此无需构建和初始化它。


作为旁注,这个签名:

void main()

无效(标准)C ++。如果要编写可移植代码,main()的返回类型应始终为int

答案 1 :(得分:2)

在第一种情况下,您没有实例化Base,但您确实调用了静态函数:

bool Base::temp = Base::initTemp();

在第二种情况下,您永远不会实例化template

template <class T>
bool Base<T>::temp = Base<T>::initTemp();

您可以显式实例化Base类模板,如:

template class Base<int>;

然后你会看到“Here”打印出来。

答案 2 :(得分:-3)

你不能创建未定义类的变量,你似乎用line:

template <class T>
bool Base<T>::temp = Base<T>::initTemp();

您无法分配未定义类型的变量。你需要的是写下这样的东西:

Base<int>::temp = value;

因为将为每个提供的类型分配不同的变量,因此您不能为模板类提供公共静态变量。您将为实例化模板的每种类型设置单独的变量。

这里的downvoters是完整的例子:

#include <iostream>

template<class T>
class X
{
public:
    static int v;
};

template<class T>
int X<T>::v = 0;

int main()
{
    X<int>::v = 3;
    X<char>::v = 2;

    using namespace std;
    cout << X<char>::v << endl << X<int>::v;
}

它打印2 3,这意味着你不能为你将实例化模板的所有类都有单个变量。