<typeinfo> 是 C++ 标准库中的头文件,用于支持运行时类型识别(RTTI)。通过 <typeinfo>,你可以在运行时获取对象的类型信息,进而进行动态类型判断、比较和调试。这个机制依赖于 C++ 中的 typeid 运算符和 std::type_info 类。


目录

  1. 简介
  2. 运行时类型识别 (RTTI)
  3. std::type_info 类
  4. 使用 typeid 运算符
  5. 典型应用场景
  6. 注意事项
  7. 结论

1. 简介

<typeinfo> 头文件提供了支持运行时类型识别的功能。通过引入此头文件,可以在程序运行时使用 typeid 运算符获得对象的动态类型信息,获取一个 std::type_info 对象,该对象保存了类型名称等信息。该机制主要用于多态类型的判断和调试。

使用时只需包含:

1
#include <typeinfo>

2. 运行时类型识别 (RTTI)

RTTI(Run-Time Type Information)允许在运行时确定对象的实际类型。通常与多态(virtual 函数)结合使用,typeid 运算符可用于比较基类指针指向的实际派生类型。动态转换(dynamic_cast)与 RTTI 紧密相关,共同支持类型安全的多态操作。


3. std::type_info 类

std::type_info<typeinfo> 中定义的类,用于存储类型的相关信息。其对象通常由 typeid 运算符返回。虽然不能直接构造或赋值 std::type_info 对象,但可以通过成员函数查询其属性。

3.1 基本成员函数

  • name():返回一个 C 风格字符串,描述类型的名称。该名称可能是编译器生成的 mangled 名称,具体格式依赖于实现。
  • before(const std::type_info& rhs):用于确定当前类型是否排在 rhs 之前,可以用于类型排序。
  • operator== 和 operator!=:用于比较两个 std::type_info 对象是否表示同一种类型。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <typeinfo>
 
class Base {
public:
    virtual ~Base() = default;
};
 
class Derived : public Base {};
 
int main() {
    Base* b = new Derived;
    // 获取动态类型信息
    const std::type_info& ti = typeid(*b);
     
    std::cout << "The dynamic type is: " << ti.name() << std::endl;
     
    // 比较类型信息
    if(ti == typeid(Derived))
        std::cout << "b 指向 Derived 类型对象" << std::endl;
    else
        std::cout << "b 不是 Derived 类型" << std::endl;
     
    delete b;
    return 0;
}

4. 使用 typeid 运算符

typeid 运算符可用于查询任意对象或表达式的类型信息。在非多态类型上,typeid 返回的是静态类型;而在多态类型上,通过指针或引用调用 typeid,则返回对象的动态类型。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <typeinfo>
 
int main() {
    int i = 42;
    double d = 3.14;
 
    std::cout << "类型 i: " << typeid(i).name() << std::endl;
    std::cout << "类型 d: " << typeid(d).name() << std::endl;
     
    // 对于多态类型,使用基类引用将得到实际派生类型
    struct Base { virtual ~Base() = default; };
    struct Derived : Base {};
     
    Derived derived;
    Base& ref = derived;
    std::cout << "ref 的动态类型: " << typeid(ref).name() << std::endl;
     
    return 0;
}

5. 典型应用场景

  • 调试与日志记录:通过输出 typeid(x).name() 可帮助调试多态对象的实际类型。
  • 类型比较:在模板或多态环境下,通过比较 std::type_info 对象来判断对象类型是否匹配。
  • 实现自定义类型系统:配合 dynamic_casttypeid 可实现自定义的类型识别与处理逻辑。

6. 注意事项

  • 名称格式name() 返回的名称可能经过名称修饰(mangling),不同编译器返回的结果格式可能不同。
  • 多态要求:对于多态类型,若使用指针或引用,则确保基类有至少一个虚函数,否则 typeid 将返回静态类型信息。
  • 性能影响:使用 RTTI 有一定运行时开销,尤其在频繁调用 typeid 时,应考虑其性能影响。

7. 结论

<typeinfo> 提供了运行时类型识别(RTTI)的支持,使得在多态环境下能够安全地判断和处理对象类型。通过使用 typeid 运算符和 std::type_info 类,你可以在调试、日志记录和模板编程中获取并比较类型信息,从而编写出更健壮和灵活的代码。

推荐阅读: