前言
在C++中,为实现不同类型间的转换,C++定义了四个类型转换操作符static_cast, const_cast, dynamic_cast, 和 reinterpret_cast。
下面介绍不同操作符的使用。
一、static_cast?
static_cast 用于平常数值类型的转换,例如:int、double、float等
书写方式:static_cast(expression)
例如,把一个 int 转换成 double,以便让包含 int 类型变量的表达式产生出浮点数值的结果。
int a, b;
...
double result = static_cast<double>(a)/b;
二、const_cast?
const_cast 用于表达式的常量性const 与 易变性volatileness 属性间的类型转换。
class Widget { ... };
class SpecialWidget: public Widget { ... };
void update(SpecialWidget *psw);
SpecialWidget sw; // sw 是一个非 const 对象。
const SpecialWidget& csw = sw; // csw 是 sw 的一个引用
// 它是一个 const 对象
update(&csw); // 错误!不能传递一个 const SpecialWidget* 变量
// 给一个处理 SpecialWidget*类型变量的函数
update(const_cast<SpecialWidget*>(&csw));
// 正确,csw 的 const 被显示地转换掉
// (csw 和 sw 两个变量值在 update函数中能被更新)
三、dynamic_cast?
dynamic_cast 用于安全地沿着类的继承关系向下进行类型转换。这就是说,你能用 dynamic_cast 把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,而且你能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转换时)或者抛出异常(当对引用进行类型转换时)
Widget *pw;
...
update(dynamic_cast<SpecialWidget*>(pw));
// 正确,传递给 update 函数一个指针
// 是指向变量类型为 SpecialWidget 的 pw 的指针
// 如果 pw 确实指向一个对象,
// 否则传递过去的将使空指针。
void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
//正确。 传递给 updateViaRef 函数
// SpecialWidget pw 指针,如果 pw
// 确实指向了某个对象
// 否则将抛出异常
dynamic_casts 在帮助你浏览继承层次上是有限制的。它不能被用于缺乏虚函数的类型上。
四、reinterpret_cast?
reinterpret_casts 的最普通的用途就是在函数指针类型之间进行转换。
typedef void (*FuncPtr)(); // FuncPtr 是一个指向函数的指针,该函数没有参数
// 返回值类型为 void
FuncPtr funcPtrArray[10]; // funcPtrArray 是一个能容纳
// 10 个 FuncPtrs 指针的数组
让我们假设你希望把一个指向下面函数的指针存入funcPtrArray 数组:
int doSomething();
你不能不经过类型转换而直接去做,因为 doSomething 函数对于 funcPtrArray 数组来说有一个错误的类型。在 FuncPtrArray 数组里的函数返回值是 void 类型,而 doSomething函数返回值是 int 类型。
funcPtrArray[0] = &doSomething; // 错误!类型不匹配
reinterpret_cast 可以让你迫使编译器以你的方法去看待它们:
funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);
总结
如果你使用的编译器缺乏对新的类型转换方式的支持,你可以用传统的类型转换方法代替 static_cast, const_cast, 以及 reinterpret_cast。也可以用下面的宏替换来模拟新的类型转换语法:
#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define dynamic_cast(TYPE,EXPR) (TYPE)(EXPR)
这些模拟不会象真实的操作符一样安全,但是当你的编译器可以支持新的的类型转换时,它们可以简化你把代码升级的过程。