You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:45:02