C++四种强制类型转换:static_cast,dynamic_cast,const_cast,reinterpret_cast

static_cast用于编译时相关的类型转换,dynamic_cast用于运行时多态类的安全向下转换,const_cast用于移除或添加const/volatile属性,而reinterpret_cast则用于低级别的位模式重新解释。

static_cast - 静态类型转换

用途

  • 相关类型间的合理转换
  • 编译时检查

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
// 基础类型转换
double d = 3.14;
int i = static_cast<int>(d); // 3

// 类层次转换(向上转换)
class Base {};
class Derived : public Base {};
Derived derived;
Base* base = static_cast<Base*>(&derived); // 安全

// 向下转换(不安全!)
Base* base_ptr = new Derived();
Derived* derived_ptr = static_cast<Derived*>(base_ptr); // 危险!

特点

  • 编译时完成
  • 不进行运行时检查
  • 相对安全(在合理范围内)

dynamic_cast - 动态类型转换

用途

  • 多态类型的安全向下转换
  • 运行时类型检查

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Base { virtual ~Base() {} };  // 必须有虚函数
class Derived : public Base {};

Base* base_ptr = new Derived();

// 安全向下转换
Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
if (derived_ptr) {
// 转换成功
} else {
// 转换失败,返回 nullptr
}

// 引用转换(失败时抛出 std::bad_cast)
try {
Derived& derived_ref = dynamic_cast<Derived&>(*base_ptr);
} catch (std::bad_cast& e) {
// 处理转换失败
}

特点

  • 运行时检查
  • 需要 RTTI(运行时类型信息)
  • 只适用于多态类型(有虚函数)
  • 安全但性能开销较大

const_cast - 常量性转换

用途

  • 添加或移除 const/volatile 限定符

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
// 移除 const
const int ci = 10;
int* modifiable = const_cast<int*>(&ci);
*modifiable = 20; // 未定义行为!原对象是 const

// 合法使用:调用旧式 API
void legacy_func(char* str);
const char* hello = "hello";
legacy_func(const_cast<char*>(hello)); // 已知字符串不会被修改

// 添加 const
int x = 42;
const int* cx = const_cast<const int*>(&x);

特点

  • 只改变常量性,不改变类型
  • 移除 const 后修改原对象是未定义行为
  • 主要用于接口兼容

reinterpret_cast - 重新解释转换

用途

  • 底层、不相关的二进制转换
  • 最危险的转换

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 指针类型转换
int x = 0x12345678;
char* bytes = reinterpret_cast<char*>(&x);

for (std::size_t index = 0; index < 4; ++index) {
cout << hex << int(bytes[0 + index]) << " ";
}
// 对于常见的小端序,输出 78 56 34 12

// 指针与整数转换
uintptr_t addr = reinterpret_cast<uintptr_t>(&x);
// 将x的地址值转换为 uintptr_t 类型
//uintptr_t是C标准库(<stdint.h>)中定义的一种无符号整数类型,它的关键特性是​​足够大,能够无损地存储任何指针值​,这比直接转换为 unsigned long等类型更安全、可移植性更好

// 如果需要将其恢复为指针
int* ptr = reinterpret_cast<int*>(addr);

// 不相关类型转换
struct A { int a; };
struct B { double b; };
A a{42};
B* bp = reinterpret_cast<B*>(&a); // 极其危险!

特点

  • 最低层的转换
  • 高度平台相关
  • 几乎不做任何检查
  • 最后的选择

对比总结

特性 static_cast dynamic_cast const_cast reinterpret_cast
安全性 中等 极低
检查时机 编译时 运行时 编译时 无检查
性能开销
主要用途 相关类型转换 多态类型安全转换 常量性修改 底层二进制转换
失败行为 可能未定义行为 返回 nullptr(指针)或抛出异常(引用) 未定义行为(如果错误使用) 几乎总是成功但危险

使用指南

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 推荐的使用顺序
// 1. 首先尝试 static_cast(如果类型相关)
// 2. 对于多态类型向下转换,使用 dynamic_cast
// 3. 需要修改常量性时,使用 const_cast
// 4. 最后才考虑 reinterpret_cast

class Base { virtual ~Base() {} };
class Derived : public Base {};

Base* base = new Derived();

// 好的实践
Derived* derived1 = dynamic_cast<Derived*>(base); // 安全检查
if (derived1) { /* 使用 */ }

// 坏的实践
Derived* derived2 = reinterpret_cast<Derived*>(base); // 危险!

核心原则:优先使用安全的转换,只在必要时使用危险的转换,并充分了解其风险。