C/C++ 强制类型转换
- 强制类型转换是一种显式地将一个类型的值转换为另一个类型的操作
- 分为 C 风格强制类型转换和 C++ 风格强制类型转换两种实现方式
- C 风格的类型转换比较简单,但缺乏类型检查,可能会引发安全问题,而 C++ 也兼容 C 风格的类型转换方式,但不推荐使用
- C++ 为提升类型转换的安全性,引入了 4 种类型转换操作符,分别针对不同场景,提升代码安全性和可读性,使转换操作更加规范,明确意图,减少歧义
(type)expression
- C 风格强制类型转换语法比较简单,但缺乏类型安全检查,可能会带来安全隐患(比如导致未定义的行为),同时也可能导致数据丢失
int a = 10;
float b = (float)a;
double d = 3.14;
int i = (int)d;
int a = 10;
int* p = &a;
void* q = (void*)p;
int arr[5] = {1, 2, 3, 4, 5};
int* p1 = arr;
char* p2 = (char*)p1;
static_cast(expression)
- 适用于基本类型之间的转换(比如 int 转 float)
- 适用于具有继承关系的类之间的指针/引用的转换
- 编译时类型检查,不进行运行时类型检查(错误的下行转换可能会导致未定义的行为)
int a = 10;
float b = static_cast<float>(a);
double d = 3.14;
int i = static_cast<int>(d);
Derived derived;
Base* basePtr = &derived;
Derived* derivedPtr = static_cast<Derived*>(basePtr);
Derived derivedObj;
Base& baseRef = derivedObj;
Derived& derivedRef = static_cast<Derived&>(baseRef);
dynamic_cast(expression)
- 适用于多态类(父类必须有虚函数)之间的转换,尤其是下行转换(父类转子类)的情况
- 运行时类型检查,如果转换失败,返回 nullptr(指针)或抛出 std::bad_cast 异常(引用)
Base* basePtr = new Derived();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
Base* b = new Base();
Derived* d = dynamic_cast<Derived*>(b);
const_cast(expression)
- 适用于添加或删除对象的 const 或 volatile 限定符
- 如果修改 const 对象的值会导致未定义的行为
const int a = 10;
int* p = const_cast<int*>(&a);
*p = 20;
reinterpret_cast(expression)
- 是一种底层(低层次、低级别)的类型转换(比如整数与指针间的转换、指针类型之间的转换),低级位模式重新解释,直接操作内存,极易引发内存解释错误,需谨慎使用
- 可能导致未定义的行为、除非绝对必要(比如硬件编程),否则应避免使用
int a = 10;
int* p = &a;
char* b = reinterpret_cast<char*>(p);
总结
- 优先使用 C++ 风格的强制类型转换,避免 C 风格的
- 优先使用 static_cast,增强类型安全
- 多态类之间的转换必须用 dynamic_cast,确保类型安全,防止运行时错误
- 仅在必要时使用 reinterpret_cast,并严格验证其正确性