输入关键词开始搜索

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) 淹没在括号里。