typeid(obj).name() 返回的是编译器 ABI 编码的 mangled 名称(如 St6vectorIiSaIiEE),不可读且跨平台不一致;必须用 abi::__cxa_demangle(GCC/Clang)或 __unDName(MSVC)解码才能获得可读类名。

typeid(obj).name() 返回的不是可读类名,而是编译器生成的 mangled 名称,直接用会出问题。
为什么 typeid(obj).name() 不能直接当类名用
它返回的是 ABI 编码后的符号名,比如 St6vectorIiSaIiEE(GCC 下 std::vector 的 mangled 名),不同编译器结果不一致,且标准不保证可读性。C++ 标准只规定 name() 返回“implementation-defined null-terminated byte string”,没说要可读。
如何安全地获取可读类名字符串
必须配合 abi::__cxa_demangle(GCC/Clang)或 UnDecorateSymbolName(MSVC)做 demangling。Linux/macOS 下推荐用:
#include#include #include #include std::string get_class_name(const std::type_info& ti) { int status = 0; std::unique_ptr
)(void)> name{ abi::__cxa_demangle(ti.name(), nullptr, nullptr, &status), [](void* p) { std::free(p); } }; return (status == 0) ? name.get() : ti.name(); } // 使用示例 struct Foo {}; Foo f; std::cout << get_class_name(typeid(f)) << "\n"; // 输出 "Foo"
-
status != 0表示 demangling 失败,退回到原始name()(不可读但不会崩溃) - 必须链接
-lstdc++(GCC)或-lc++(Clang) - MSVC 用户需改用
__unDName,且typeid(T).name()本身已部分 demangled,行为不同
替代方案:C++11 起可用模板 + __PRETTY_FUNCTION__
更便携、无需链接额外库,适合调试和日志:
立即学习“C++免费学习笔记(深入)”;
templatestd::string type_name() { const char* p = __PRETTY_FUNCTION__; const char* q = strrchr(p, ' '); if (!q) return ""; q++; const char* r = strchr(q, '['); return std::string(q, r ? r - q : strlen(q)); } // GCC/Clang 下 type_name
() → "Foo" // 注意:MSVC 不支持 __PRETTY_FUNCTION,需用 FUNCSIG__
- 依赖编译器扩展,不是标准 C++,但 GCC/Clang 稳定支持
- 不适用于运行时对象(只能在编译期推导类型),即不能写
type_name后再传参() - 若类在匿名命名空间里,可能带额外修饰,需额外截取
真正可靠的运行时类名获取,绕不开 demangling;而编译期已知类型的场景,__PRETTY_FUNCTION__ 更轻量。别信 “typeid(x).name() 就是类名” 这种说法——它只是个符号标识符,不是名字。










