C++中模板类中的静态字段初始化

Static field initialization in template class in C++

本文关键字:静态 字段 初始化 C++      更新时间:2023-10-16

我正试图在C++中创建一些自注册类。所以我尝试了类似于这里提供的解决方案。在做这件事的时候,我偶然发现了一些奇怪的东西。

这是代码:

#include <iostream>
class StaticClassType {
public:
  StaticClassType() {
    // Notify when the static member is created
    std::cout << "We're in." << std::endl;
  }
};

template<typename T>
class TestClass1 {
public:
  TestClass1() { &m; }
private:
  // Static member in a template class
  static StaticClassType m;
};
template<typename T>
StaticClassType TestClass1<T>::m;

class TestClass2 : public TestClass1<TestClass2> {
public:
  TestClass2() { } // required; why?
};

int main() {
  return 0;
}

此代码在启动时创建静态成员变量TestClass1::m(从而将"We are in."打印到控制台),即在main()启动之前。但是,只有当我为TestClass2编写一个(空的)构造函数时,代码才能工作(如示例所示)。

为什么我需要编写这个构造函数?为什么编译器生成的默认构造函数不做同样的事情?

此问题仅发生在模板类中。如果TestClass1不是一个模板类,那么代码将在不为TestClass2编写空构造函数的情况下工作。

我创建了一个更小的例子(没有构造函数,这是不需要的):

#include <iostream>
class StaticClassType {
public:
  StaticClassType(int v) {
    // Notify when the static member is created
    std::cout << "We're in."<<v << std::endl;
  }
};

template<typename T>
class TestClass1 {
protected:
  // Static member in a template class
  static StaticClassType m;
};
template<typename T>
StaticClassType TestClass1<T>::m = StaticClassType(3);

class TestClass2 : public TestClass1<TestClass2> {
public:
    void foo()
    {
        (void)m;
    }
};
int main() {
  std::cout << "main" << std::endl;
}

注意,需要使用foo()方法,否则编译器会删除静态变量,因为它不会在任何地方使用。

从我的角度来看,"问题"是在"模板世界"中,编译器将只生成客户端代码真正使用的内容。在这里,您永远不会实例化TestClass2类。因此,不会生成大量代码。尝试:

int main() {
  TestClass2 instance;
  return 0;
} 

然后它就起作用了。