我们知道,C++ 有四个与类型转换有关的关键字:const_cast、dynamic_cast、static_cast 和 reinterpret_cast,很容易混淆它们各自的用法,下面我来简单总结一下每个关键字的使用场景(原则上尽量不用类型转换操作,但是不得不用时也尽量使用这几个新式的转型操作,因为它们分工比较明确且容易识别):

1. const_cast 关键字

用途:转掉对象的 const 属性或者 volatile 属性,也是唯一能做到这一点的新式转型操作:

const int constant = 42; // local const
constant = 0; // error: read-only variable is not assignable
const_cast<int&>(constant) = 0; // normal expression
cout << constant << endl; // 42
cout << *(&constant) << endl; // 0

注意:两个输出结果可能会让人费解,具体原因是这样的:局部 const 只在编译期保证不能为其赋值,运行时可以使用 const_cast 操作修改其在内存中的值,所以 *(&constant) 输出为 0;另外编译器会直接用立即数替换该常量的引用,所以 constant 的输出值仍然是 42。另外需要注意,全局 const 分配在只读内存区,试图以任何方式修改它都会引发运行时错误。

2. dynamic_cast 关键字

用途:主要用于执行“安全向下转型”,这是旧式的转型操作唯一做不到的,也是唯一可能耗费巨大成本的(其实现机制基于“class名称字符串的比较”,避免在注重效率的场合使用),一般用于无法使用虚函数的场合,用法:dynamic_cast<T& 或者 T*>();

3. static_cast 关键字

用途:主要用于强制类型转换,如将 non-const 转换为 const(但不能将 const 转为 non-const)、将 int 转为 double、将 void* 转为特定类型的指针或者将基类指针转换为指向派生类的指针,但是与 dynamic_cast 有些区别:
(1)static_cast 无类型检查;dynamic_cast 有类型检查,若转型失败则返回空指针:

void func(Base *pb)
{
Derived *pd1 = static_cast<Derived *>(pb); // without type checking
Derived *pd2 = dynamic_cast<Derived *>(pb); // type checking
}

(2)dynamic_cast 转换的类必须要有虚函数,否则编译错误;static_cast 无此限制;
(3)dynamic_cast 支持无继承关系的类之间转换,结果是失败并返回空指针;static_cast 则会直接编译错误。

4. reinterpret_cast 关键字

用途:一般用来进行不同性质的类型之间的转换,如将指针转换为整数。用法:reinterpret_cast<T>(),其中 T 必须是一个指针、引用或者算数类型,需要注意的是其可移植性不是很好。