强制转换用于调整编译器对表达式类型的解读。编译器会解析源码,理解所写的内容,以及他人代码所表达的含义。大多数时候(理想情况下),这些代码合理,编译器会无异议地将源码转换为正确的二进制文件。
当然,有时开发者意图与编译器所见的代码表达之间会存在差异。多数情况下,编译器获胜,开发者会根据错误或警告提示(以其独特的方式揭示问题)重写部分源码,以更准确地表达意图。偶尔源码确实符合开发者意图,却仍与编译器产生分歧,此时需要通过调整来达成一致。假设开发者需要分配一个足够大的缓冲区来存储大量整数(“大量”可能指栈空间无法容纳的大小,或编译时未知的值),一种(底层、易出错但仍合法的)实现方式是调用 std::malloc() 函数:
// ...
int *p = std::malloc(lots * sizeof(int)); // <-- HERE
if(p) {
// 使用p作为int对象的数组
std::free(p);
}
// ...
这段代码并非有效的 C++ —— std::malloc() 返回 void*(指向至少请求大小的原始内存块的指针,若分配失败则返回 nullptr),而 C++ 中 void* 不能隐式转换为 int*(反之也成立 —— int* 确实可隐式转换为 void*)。
这个(过度简化的)案例中,本可用 new int[lots] 替代 std::malloc(lots*sizeof(int)),但实际情况往往更复杂,有时需要暂时“欺骗”类型系统。这正是使用强制转换的地方。
那么,何为强制转换?它是引导编译器类型系统理解开发者意图的可控方式。转换操作不仅为源码中这种“临时谎言”提供理由说明,还记录了开发者在需要违背类型系统时的真实意图。C++ 的强制转换能清晰传达意图并精准生效;而 C 风格转换(也见于其他语言)在意图表达上则模糊得多(本章后续将展开讨论),在 C++ 这样拥有丰富类型系统的语言中,可能会执行不恰当的转换。