Skip to content

RTTI 与 dynamic_cast 实现分析

RTTI(Run-Time Type Information)提供运行时类型信息,dynamic_cast 用于安全的向下转换。本文分析 GCC 和 LLVM 的 RTTI 实现。


一、核心概念

1.1 什么是 RTTI

RTTI 提供运行时类型信息:

cpp
// typeid 获取类型信息
Base* p = new Derived();
const type_info& ti = typeid(*p);
cout << ti.name() << endl;  // 输出类型名

// dynamic_cast 安全转换
Derived* d = dynamic_cast<Derived*>(p);
if (d) {
    // 转换成功
}

二、核心数据结构

2.1 type_info

type_info 的结构:

┌─────────────────────────────────────┐
│ vptr(type_info 的虚函数表)         │
├─────────────────────────────────────┤
│ __typeinfo_name(类型名)            │
└─────────────────────────────────────┘

存储位置:
  · .rodata 段(只读数据)
  · 每个类型一个 type_info 对象

2.2 dynamic_cast 的实现

dynamic_cast 的实现:

1. 获取源类型的 type_info
2. 获取目标类型的 type_info
3. 比较 type_info 是否匹配
4. 计算指针偏移量(多重继承时)
5. 返回调整后的指针

性能:
  · 同类型:O(1)
  · 单继承:O(depth)
  · 交叉转换:O(N)

三、GCC vs LLVM 差异对比

┌────────────────────────┬──────────────────────┬──────────────────────┐
│ 特性                    │ GCC                  │ Clang/LLVM           │
├────────────────────────┼──────────────────────┼──────────────────────┤
│ type_info              │ 支持                 │ 支持                 │
│ typeid                 │ 支持                 │ 支持                 │
│ dynamic_cast           │ 支持                 │ 支持                 │
│ -fno-rtti              │ 支持                 │ 支持                 │
│ type_info 名称         │ mangled name         │ mangled name         │
│ 比较运算符             │ ==                   │ ==                   │
└────────────────────────┴──────────────────────┴──────────────────────┘

四、最佳实践

RTTI 使用指南:

1. 优先使用虚函数:
   · 比 dynamic_cast 更高效
   · 更面向对象

2. 谨慎使用 dynamic_cast:
   · 有运行时开销
   · 可能抛异常

3. 使用 -fno-rtti:
   · 减小二进制体积
   · 使用枚举 ID 替代

4. 使用 typeid 获取类型名:
   · 调试时有用
   · 日志记录

延伸阅读

基于 MIT 许可发布