如何从C++静态基类方法获取当前类类型ID及类型?
从静态基类方法获取子类类型ID的解决方案
这确实是个挺常见的痛点——子类数量多的时候,挨个加虚函数或者重复代码实在太繁琐了。先直接给结论:普通的静态基类方法没法直接获取调用它的子类类型,因为C++里静态成员是编译期绑定的,B::getClassType()本质上还是调用基类A的静态方法,自然拿不到B的std::type_info。
不过我们可以用**奇异递归模板模式(CRTP)**来解决这个问题,不需要给每个子类额外添加代码,只需要继承的时候做一点小改动:
实现方案
首先把基类改成模板类,将子类作为模板参数传递进去:
#include <typeinfo> template<typename Derived> class A { public: static const std::type_info& getClassType() { // 直接返回模板参数Derived的类型信息 return typeid(Derived); } };
然后子类继承基类时,把自己作为模板参数传入:
class B : public A<B> { }; class C : public A<C> { }; class D : public A<D> { }; // ... 其他子类都这么写
现在调用子类的静态方法就能得到正确的类型信息了:
B instance; auto my_type = B::getClassType(); // my_type == typeid(B)
为什么这个方案可行?
因为每个子类继承的是不同的基类模板实例(比如B继承的是A<B>,C继承的是A<C>),每个模板实例的getClassType静态方法都是独立的,返回的是对应Derived参数的typeid结果。这就绕开了C++不支持静态成员重载的限制,而且不需要在子类里写任何额外的虚函数或重复代码。
额外注意点
- 如果你的子类还有更深的继承层级(比如E继承自B),那么E需要继承
A<E>而不是直接继承B,否则E::getClassType()会返回B的类型信息。 typeid是运行期操作,但这里因为Derived是模板参数,编译器可以在编译期就确定typeid(Derived)的结果,不会有额外的运行期开销。- 如果你不想用模板,也可以用宏来自动生成子类的静态方法,但宏的可读性和安全性远不如CRTP,不推荐。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

