C++调用基类继承的静态方法时如何获取派生类名且无需实例化
问题原因
C++的静态成员函数不与具体类实例绑定,也不会在继承时根据调用的派生类类型动态适配,__FUNCTION__是编译期展开的宏,你用Milk.RegisterClass()本质调用的还是基类Product的静态函数,所以只会展开得到Product::RegisterClass。
解决方案:使用CRTP(奇异递归模板模式)实现
这是C++中无需实例化、在基层静态方法中获取派生类类型信息最常用的方案,完全匹配你的需求:
完整示例代码
辅助函数与基类定义
#include <string> #include <typeinfo> #include <cxxabi.h> #include <cstdlib> // 辅助函数:消除编译器对类型名的修饰,GCC/Clang可用,MSVC可自行适配对应接口 std::string get_clean_class_name(const char* mangled_name) { int status = 0; char* demangled_str = abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status); std::string res = demangled_str ? demangled_str : mangled_name; free(demangled_str); return res; } // CRTP模板基类,模板参数为派生类类型 template <typename Derived> class Product { public: static void RegisterClass() { // 直接获取派生类的纯净类名,可直接用于注册 std::string class_name = get_clean_class_name(typeid(Derived).name()); // 如需拼接为 Milk::RegisterClass 格式,可按如下写法 std::string b = class_name + "::RegisterClass"; // 此处可添加你的注册逻辑,直接用class_name即可拿到"Milk"字符串 }; };
派生类定义
// 派生类继承时将自身作为模板参数传入基类,注意要使用public继承 class Milk: public Product<Milk> {}; // 后续新增派生类不需要重复写RegisterClass逻辑,只需按如下格式继承即可 class Bread: public Product<Bread> {};
主函数调用
int main() { // 无需实例化,静态调用即可 Milk::RegisterClass(); // 可拿到"Milk"字符串 Bread::RegisterClass(); // 可拿到"Bread"字符串 return 0; }
方案说明
- 整个流程完全不需要对类进行实例化,全部为静态调用,符合你的要求
- 新增派生类时不需要重复编写注册逻辑,只需要继承
Product<派生类名>即可,维护成本低 - 如果不需要
Milk::RegisterClass格式,直接用class_name变量即可拿到纯净的派生类名用于注册,完全匹配你的最终目标
内容的提问来源于stack exchange,提问作者Aryan Firouzian
相关产品推荐
相关产品推荐

