除了由编译器根据需要自动进行的隐式类型转换外,也可以手动强制将一个对象显式转换为另一种相关的类型,C++提供了4种强制类型转换的方法。
static_cast <type> (expr)
在算术表达式中,常用static_cast来执行以下二种操作。
执行浮点数操作,例如:
int i = 5, j = 3;
double k = i /static_cast <double> (j) //强制将j的值转化为double类型
告诉编译器用户有意将宽类型转换为窄类型,请关闭警告信息,例如:
double i = 5., j = 3.;
int k = i /static_cast <int> (i / j) //强制将i / j的结果转化为int类型
dynamic_cast <type> (expr)
运行时类型识别(Run-Time Type Identification, RTTI)指的是通过基类的指针或引用来检查其指向的派生类型。RTTI提供的dynamic_cast运算符作用于基类的指针或引用,如果该类型含有虚函数,则返回基类指针或引用的动态类型;否则返回该类型的静态类型。
dynamic_cast一般用于基类指针或引用到派生类的转换,因为C++支持派生类指针或引用到基类的自动转换。成功转换的前提是,expr的类型必须是type的基类、派生类或type本身;否则转换失败。在转换失败的情况下,如果是指针类型转换,则返回空指针;如果是引用转换,则抛出一个std::bad_cast异常(bad_cast的基类为excetion)。
/*dynamic_cast的使用方式有如下3种。其中type必须是一个类类型,通常情况下,该类型应含有
虚函数成员。在第一中方式中,expr必须为有效的指针;在第二种方式中,expr必须为左值;在第
三种方式中,expr必须为右值(C++11引入)。*/
dynamic_cast<type*>(expr)
dynamic_cast<type&>(expr)
dynamic_cast<type&&>(expr)
//1)使用指针类型的dynamic_cast:
struct Base {
virtual ~Base() {}
};
struct Derived:Base {
void name() {}
};
/*在下述两处转换调用均将Base类型指针转换为Derived类型指针。对于第一个转换,由于b1与基类
对象绑定,不能将其转换为派生类型,因此转换失败,d的结果为空指针,不会执行name调用;对于第
二个转换,虽然b2也是基类指针,但由于b2与派生类对象绑定,因此可以将其转换为派生类型,转换的
结果为将b2的值赋给d,并调用name函数。*/
Base *b1 = new Base, *b2 = new Derived;
if(Derived *d = dynamic_cast<Derived*>(b1))
d->name(); //转换失败,d为nullptr,不会执行此调用
if(Derived *d = dynamic_cast<Derived*>(b2))
d->name(); //转换成功,执行此调用
//2)使用引用类型的dynamic_cast:
/*引用类型和指针类型的dynamic_cast的区别在于错误的报警方式不同。由于没有空引用,因此当
引用类型转换失败时,程序将抛出一个std::bad_cast异常,该异常定义在typeinfo标准库文件中。
例如上面的Base类指针所指向的对象转换为Derived类的引用时,会抛出此异常。*/
try { //转换失败,抛出std::bad_cast异常
Derived &d = dynamic_cast<Derived&>(*b1);
} catch(std::bad_cast) {
cout << "downcast failed" << endl;
}
reinterpret_cast <type> (expr) 和 const_cast <type> (expr)
const_cast用来去掉对象的const属性,即把const对象转换成非const对象。在程序中一般很少使用这二种。