16 / 80 · C++11 · 约 10 分钟
四种 cast:转换意图与安全前提
static_cast、dynamic_cast、const_cast 与 reinterpret_cast 分别表达不同转换意图,但关键字本身不保证运行安全。选择前先证明数值范围、动态类型、实际可修改性,以及对象生命期、对齐和类型访问规则。
数值转换与类型层次
static_cast 用于明确允许的数值转换、某些类层次转换以及其他静态可描述转换。它不会自动检查值是否越界;浮点转整数应先确保截断后的值可表示,下行转换则必须真的指向相应派生对象,不能靠程序员的猜测。
dynamic_cast 在多态类层次中进行需要的运行时检查,适合动态类型不确定的下行或横向转换。指针形式失败返回空指针,引用形式失败抛出 std::bad_cast。它仍要求输入对象有效并处于适当生命期,不能用来验证任意损坏地址。
限定转换与底层解释
const_cast 改变 const 或 volatile 等限定,不改变实际对象本来是否可修改。示例从指向普通 int 的只读指针恢复可写访问,所以写入合法;若原对象定义为 const,再经转换写入就会是未定义行为。
reinterpret_cast 表达底层表示或指针层面的重新解释,但不自动创建目标对象、满足对齐或解除类型访问限制。把 float* 转成 int* 再读取并不是通用的位模式查看方法;合适场景可使用 memcpy,C++20 也提供受类型与大小约束的 bit_cast。
让危险前提可以被审查
C 风格转换语法简短,却可能组合多种转换能力,让读者难以辨认是否去掉了 const 或进行了底层重解释。新代码优先使用具名转换,把危险点变得可搜索;但更好的设计往往是不需要转换,例如使用正确的接口类型或虚函数。
示例验证成功与失败的动态转换、已知安全范围内的数值转换,以及原对象确实非 const 的限定转换。所有前提都在相邻代码中可见,不执行错误转换来“观察结果”。面试回答也应说明前提和失败行为,而不是只列出四个英文名字。
容易答错的地方
- static_cast 从基类向派生类转换不执行运行时类型验证;转换能编译不是对象类型正确的证明。
- reinterpret_cast 成功产生某个指针值,不等于允许通过该类型解引用;生命期、对齐、类型可访问性必须分别成立。
运行一个例子
最低标准 C++11 · 完整程序 · 下载 .cpp
#include <cassert>
#include <iostream>
struct Base { virtual ~Base() = default; };
struct Derived : Base { int value = 7; };
struct Other : Base {};
int main() {
Derived object;
Base* base = &object;
Derived* derived = dynamic_cast<Derived*>(base);
assert(derived != nullptr && derived->value == 7);
assert(dynamic_cast<Other*>(base) == nullptr);
int editable = 3;
const int* read_only = &editable;
*const_cast<int*>(read_only) = 4;
const int whole = static_cast<int>(3.75);
assert(editable == 4 && whole == 3);
std::cout << derived->value << ' ' << editable << ' ' << whole << '\n';
}
在本地编译
g++ -std=c++11 -Wall -Wextra -Wpedantic -pthread basics-casts.cpp -o example && ./example预期结果
7 4 3
CHECK YOUR UNDERSTANDING
合上答案,试着解释。
const int fixed = 5; const int* p = &fixed;。const_cast<int*>(p) 能形成吗?能否通过结果写入 6?若改用 dynamic_cast<Derived&> 失败又会怎样?
查看参考答案
可以形成去掉限定的指针,但写入 6 非法,因为实际对象从定义起就是 const,修改会产生未定义行为。转换表达式合法与后续访问合法是两回事。dynamic_cast 的引用形式没有空引用作为失败值,因此检查失败会抛出 std::bad_cast,应捕获该异常或在允许失败时选择指针形式。
继续查证
标准草案链接会随工作草案更新;本文版本标记对应示例最低要求,不表示草案中的所有新规则都适用于旧标准。