static_cast 以下命名为A
const_cast 以下命名为B
dynamic_cast 以下命名为C
reinterpret_cast 以下命名为D
C 风格的类型转换(type)expression 以下命名为E
首先声明一点: E无所不能,从功能上可以完全取代A, B, C, D
注意,我这里只说了 "从功能上" 注意我的措辞
为什么C++编译器要引入 A, B, C, D ? 就是因为 E 太粗鲁,太暴力,不小心引入错误了,编译器却发现不了
这就好比C语言的数组,一不小心就越界了,就越界还好,你还把后面数据给覆盖了,找问题你就哭吧,
这就是为什么C++有容器的原因之一,你错了,只管自己错
A 几乎 就是C++版的 E
除了 不能: -- 去除 const 属性
-- 不能把 Struct 转换成 int
-- 不能把 double 转换成 指针
B 用于转换掉 表达式 的 const 或 volatileness 属性
如果你试图使用 const_cast 来完成 constness 或者 volatileness 属性之外的事情,你的类型转换将会被拒绝
注 : const_cast 只对 "指针&引用" 有效
class Widget { } ;
class SpecialWidget : public Widget { } ;
void Update(SpecialWidget* psw) ;
SpecialWidget sw ;
const SpecialWidget& csw = sw ;
Update(const_cast<SpecialWidget*>(&csw)) ; // 正确
Update((SpecialWidget*)&csw) ; // 正确 但用了C风格的类型转换 [亲测有效]
C dynamic_cast 把指向基类的指针或引用转换成指向派生类的指针或引用
转换成功,指针非空
转换失败返回空指针(当对指针进行类型转换时) 或 抛出异常(当对引用进行类型转换时)
如果没有虚函数, 即便两个类有继承关系,转换也不成功 [亲测是这样的]
D reinterpret_cast转换结果几乎是执行期定义。因此用 reinterpret_cast 的代码很难移植
最普通的用途就是在函数指针类型之间的转换
typedef void (*FunPtr)() ;
FunPtr funcPtrArray[10] ;
int doSomething() ;
funcPtrArray[0] = &doSomething ; // 错误
funcPtrArray[0] = reinterpret_cast<FunPtr>(&doSomething) ; // 正确
好了,到此为止,基本上讲完了
再回到最开始,我说 E 无所不能 但是只是 "从功能上", 因为用 E 我可以模拟出 A,B,C,D
*1 #define my_static_cast(TYPE, EXPR) ((TYPE)(EXPR))
*2 #define my_const_cast(TYPE, EXPR) ((TYPE)(EXPR))
*3 #define my_dynamic_cast(TYPE, EXPR) ((TYPE)(EXPR))
*4 #define my_reinter_cast(TYPE, EXPR) ((TYPE)(EXPR))
虽然都能达到目的,并且编译器也允许 从 "功能上" 实现了 A,B,C,D
但是没有编译层面的安全检查
比如 *4 如果你转向的不是子类 编译器也会让你成功通过
More Effective C++--条款2: 尽量使用 C++风格的类型转换
最新推荐文章于 2020-05-14 13:22:24 发布