7

在以下程序中打印“Here”:

#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;}

在以下程序中不打印“Here”:

#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。

4

3 回答 3

6

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

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

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

这在 C++11 标准的第 14.7.1/1 段中指定:

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

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


作为旁注,这个签名:

void main()

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

于 2013-07-08T14:15:00.283 回答
2

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

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

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

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

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

template class Base<int>;

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

于 2013-07-08T14:20:38.740 回答
-3

您无法创建未定义类的变量,您似乎可以使用以下行:

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

您不能分配未定义类型的变量。你需要的是这样写:

Base<int>::temp = value;

当然,将为提供的每种类型分配不同的变量,因此您不能为模板类使用公共静态变量。对于您实例化模板的每种类型,您将拥有单独的变量。

这里的投票者是完整的例子:

#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 这意味着您不能为所有要实例化模板的类使用单个变量。

于 2013-07-08T14:17:24.637 回答