什么时候在C ++中调用模板类的静态成员的构造函数?

时间:2011-08-05 16:38:07

标签: c++ templates constructor static-members

有很多关于何时调用普通类的静态成员的构造函数的信息。但是,我看到一些关于模板类的奇怪行为。

以下程序的输出应该是什么? (注意我使用printf来避免任何静态初始化命令与std :: cout的混淆并发症。)

#include <iostream>

class B {
public:
  B(const std::string &s) { printf("Hello I am B from %s\n", s.c_str()); }
};

template<typename T>
class Atempl {
public:
  static B b_;
};

class A {
public:
  static B b_;
};

template<typename T>
B Atempl<T>::b_("Atempl");
B A::b_("A");

class C : public Atempl<int> {
};

int main(int argc, const char *argv[]) {
  return 0;
}

我认为输出应该是:

Hello I am B from A
Hello I am B from Atempl

但是使用FreeBSD 7.3上的g ++ 4.3,我得到了:

Hello I am B from A

如果我添加行

template class Atempl<int>;

一切都很好,我得到了预期的输出。问题是,为什么C类的声明不算作模板的实例化     Atempl 并导致B的构造函数被调用?这是标准的一部分还是g ++ 4.3中的错误?

3 个答案:

答案 0 :(得分:10)

在类模板中,执行隐式实例化时,会根据需要实例化成员。由于代码不使用静态成员,因此甚至不在整个应用程序中实例化。

当你进行显式的实例化时,整个类及其所有成员都会被实例化,并且包含静态成员变量,然后对其进行初始化并获得预期的结果。

如果没有显式实例化,您可以执行B* p = &Atempl<int>::b_;(或静态成员的任何其他用法)来触发实例化。

答案 1 :(得分:3)

当初始化类模板模板的静态成员时 不确定的。实际上,除非你实际使用静态成员,否则它 不应该实例化,所以永远不要初始化。如果你 显式实例化模板,强制实例化所有 成员,反过来强制初始化(但我认为 究竟什么时候它将被初始化仍未指定。)

答案 2 :(得分:0)

在进程开始后和调用main()之前的某个时间,它们由C ++运行时调用。 “常规”类和类模板实例之间没有区别。调用构造函数的顺序是未定义的。