C++ 类型转换 — static_cast / dynamic_cast / const_cast / reinterpret_cast
四种 cast 总览
| cast | 用途 | 运行时检查 | 安全性 |
|---|---|---|---|
static_cast | 相关类型间转换 | ❌ 编译期 | 中 |
dynamic_cast | 多态类型安全向下转型 | ✅ 运行时 | 高 |
const_cast | 添加/移除 const | ❌ | 低(慎用) |
reinterpret_cast | 任意指针/整数互转 | ❌ | 极低(尽量不用) |
static_cast — 最常用
// ① 基本类型转换
double d = 3.14;
int i = static_cast<int>(d); // 3 — 明确表示"我知道精度损失"
// ② 基类 → 派生类(不检查安全性!)
Base *b = new Derived();
Derived *d = static_cast<Derived *>(b); // ⚠️ 如果 b 不是 Derived → UB
// ③ void* → T*(合法且安全)
void *ptr = malloc(100);
int *arr = static_cast<int *>(ptr);
// ④ 枚举 ↔ 整数
enum Color { RED = 0, GREEN = 1 };
int val = static_cast<int>(GREEN);
dynamic_cast — 安全的向下转型
class Base { virtual ~Base() = default; }; // ⚠️ 必须有虚函数
class Derived : public Base {};
Base *b = new Derived();
if (auto *d = dynamic_cast<Derived *>(b)) {
d->derivedMethod(); // 安全
}
// 失败: 返回 nullptr(指针)或抛 std::bad_cast(引用)
// 引用版
Derived &dr = dynamic_cast<Derived &>(*b); // 失败抛异常
// 交叉转型(多重继承中)
class A { virtual ~A() = default; };
class B { virtual ~B() = default; };
class C : public A, public B {};
B *bp = new C();
A *ap = dynamic_cast<A *>(bp); // ✅ 可以:C 同时是 A 和 B
运行时开销
dynamic_cast 需要 RTTI(Run-Time Type Information)
- 编译器生成 type_info 表
- 每次 dynamic_cast 查表比较类型
- 开销约为虚函数调用的 5-10 倍
关闭 RTTI: gcc -fno-rtti
→ dynamic_cast 不可用(编译不过)
→ typeid 不可用
const_cast — 去 const
// 唯一合法用途:兼容旧 API
void legacyApi(char *str); // 旧 API 没写 const
const char *msg = "hello";
legacyApi(const_cast<char *>(msg)); // ✅ 旧 API 实际不修改
// ❌ 危险:试图修改真正的常量
const int x = 42;
int *p = const_cast<int *>(&x);
*p = 100; // 未定义行为!x 可能被编译器优化为立即数
reinterpret_cast — 最危险
// 经典用途:网络编程字节转换
int val = 0x12345678;
char *bytes = reinterpret_cast<char *>(&val);
// 大端: bytes[0]=0x12, 小端: bytes[0]=0x78
// 对象字节级复制
struct Packet { int id; double val; };
Packet pkt{1, 3.14};
char buffer[sizeof(Packet)];
memcpy(buffer, reinterpret_cast<char *>(&pkt), sizeof(pkt));
// ❌ 函数指针互转 → 几乎总是 UB
typedef void (*FuncA)();
typedef int (*FuncB)(int);
FuncA fa = []{};
// FuncB fb = reinterpret_cast<FuncB>(fa); // UB!
选择决策树
基类 → 派生类(多态)?
├─ 是 → dynamic_cast(安全)
└─ 否 → 相关类型?
├─ 是 → static_cast
└─ 否 → 去/加 const?
├─ 是 → const_cast(确认旧 API 不修改)
└─ 否 → 必须这样?
├─ 是 → reinterpret_cast(加注释说明原因)
└─ 否 → 重构设计
C 风格转换 vs C++ cast
// C 风格 — 什么都干,看不出意图
Derived *d = (Derived *)base; // 是 static? dynamic? reinterpret?
// C++ — 意图明确
Derived *d = dynamic_cast<Derived *>(base); // 读代码的人立刻知道:多态转型
int i = static_cast<int>(3.14); // 数值转换,精度损失
永远用 C++ cast:grep 搜索时 static_cast 可以找到所有转换点,(type) 淹没在括号里。