读书笔记:最好使用C++转型操作符
《More Effective C++:35个改善编程与设计的有效方法》
读书笔记:最好使用C++转型操作符
主要围绕C++转型操作符展开,核心是推荐使用C++新式转型操作符而非C旧式转型,具体总结如下:
一、C旧式转型的缺点
- 功能宽泛不精确:允许几乎任意类型间的转换,无法精确表达转型意图(如仅改变常量性与继承体系下的类型转换无法区分)。
- 难以辨识:语法为
(type)expression
,小括号和标识符在C++中随处可见,人类和工具(如grep)难以快速识别是否为转型操作。
二、C++新式转型操作符(4种)
新式转型操作符更精确、易辨识,各有特定用途,编译器可检测错误,替代了C旧式转型的模糊性。
-
static_cast
- 功能与C旧式转型基本一致(同限制),但语法为
static_cast<type>(expression)
,易辨识。 - 用途:常规类型转换(如int转double)、非const性的类型转换(但不能移除const性)。
- 限制:不能将struct转int、double转指针,也不能改变表达式的常量性(需用const_cast)。
- 功能与C旧式转型基本一致(同限制),但语法为
-
const_cast
- 专用于改变表达式的常量性(constness) 或变易性(volatileness),明确表达仅为此目的。
- 限制:若用于其他转型(如继承体系下的类型转换),会被编译器拒绝。
- 示例:将
const SpecialWidget*
转为SpecialWidget*
,移除常量性以适配函数参数。
-
dynamic_cast
- 用于继承体系中安全的向下转型或跨系转型,可检测转型是否成功(指针转型失败返回null,引用转型失败抛异常)。
- 限制:仅适用于含虚函数的类型(依赖多态),不能改变常量性(需先经const_cast处理),不涉及继承的转型不支持。
-
reinterpret_cast
- 用于底层、低阶转型,结果依赖编译平台,移植性差。
- 典型用途:转换函数指针类型(如将返回int的函数指针转为返回void的函数指针)。
三、编译器不支持新式转型的替代方案
- 可用宏模拟static_cast、const_cast、reinterpret_cast(如
#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
),但安全性不如原生操作符。 - dynamic_cast难以模拟,无原生支持时可用旧式转型,但无法检测转型是否成功。
四、总结:推荐使用C++新式转型的原因
- 意图更精确,易被人类和工具识别;
- 编译器可诊断旧式转型无法检测的错误;
- 语法虽冗长,但“丑陋”反而减少滥用,促使谨慎使用转型。
综上,C++新式转型操作符在精确性、可辨识性和安全性上优于C旧式转型,应优先使用。