typeid不能做反射,仅提供不可靠、不跨平台的类型名和类型比较,且std::type_info禁止拷贝,只能取引用;对非多态类型返回静态类型,多态类型需通过指针或引用触发动态查询;name()不可移植,应使用typeid(x) == typeid(T)比较;它不具备成员枚举、字段访问等反射能力。

typeid 不能做反射,它只提供最基础的运行时类型名和类型比较能力,且结果不可靠、不跨平台、不支持自定义行为。
typeid 返回的是 type_info 引用,不是字符串也不是可拷贝对象
你不能直接把 typeid(obj) 赋值给变量或存进容器,因为 std::type_info 禁止拷贝和赋值:
auto t = typeid(obj); // ❌ 编译失败:type_info 拷贝构造函数被删除 const std::type_info& t = typeid(obj); // ✅ 正确:只能取引用
常见误用是想缓存类型信息做后续判断,结果编译不过。如果真要“记住”某个类型,得用 typeid(T).hash_code() 或 typeid(T).name()(但后者不可移植)。
name() 返回的字符串是编译器私有格式,不能用于比较或解析
typeid(int).name() 在 GCC 可能返回 "i",Clang 是 "i" 或 "int",MSVC 是 "int" —— 完全没标准。所以:
立即学习“C++免费学习笔记(深入)”;
- ❌ 不要用
std::string(typeid(x).name()) == "std::vector判断类型" - ✅ 应该用
typeid(x) == typeid(std::vector直接比) type_info引用 - ⚠️ 注意:
typeid对非多态类型(无虚函数的类)返回静态类型,不是实际动态类型
typeid 在多态类型上才反映真实运行时类型,但仍有陷阱
只有当操作的对象是指针或引用,且其静态类型是多态类(含至少一个虚函数)时,typeid 才执行动态类型查询:
struct Base { virtual ~Base() = default; }; // ✅ 多态
struct Derived : Base {};
Base p = new Derived;
std::cout << typeid(p).name(); // 输出 Derived 的类型名(动态类型)
Base b;
std::cout << typeid(b).name(); // 仍是 Base(静态类型,无虚函数调用也无动态查询)
容易踩的坑:
- 对普通对象(非指针/引用)用
typeid,永远得到声明时的静态类型 - 对
void*或未开启 RTTI 的编译(如 GCC-fno-rtti),typeid直接报错或未定义行为 - 类型相等比较(
==)是安全的,但hash_code()在同一程序中相同类型一定一致,跨程序/跨次运行不保证
别指望 typeid 实现反射:它没有成员枚举、没有字段访问、没有构造调用
C++ 标准里没有反射机制,typeid 连类有多少成员变量都不知道。所谓“RTTI 支持反射”是常见误解。如果你需要类似功能:
- 手动写类型映射表(比如
std::map配合hash_code()) - 用宏生成类型注册 + 字段描述(如 Boost.PFR 的零开销方案)
- 借助 Clang LibTooling 或 C++20
reflexpr(实验性,非标准)做编译期提取
真正上线项目里,依赖 typeid 做逻辑分发往往意味着设计已偏离面向对象原则——优先考虑虚函数、访问者模式或类型擦除(如 std::any + std::type_index)。










