static_cast和dynamic_cast详解
类继承关系图
注:从图中可以看出,派⽣类不仅有⾃⼰的⽅法和属性,同时它还包括从⽗类继承来的⽅法和属性。当我们从派⽣类向基类转换时,不管⽤传统的c语⾔还是c++转换⽅式都可以百分百转换成功。但是可怕是向下转换类型,也就是我们从基类向派⽣类转换,当我们采⽤传统的C语⾔和c++转换时,就会出现意想不到的情况,因为转换后派⽣类⾃⼰的⽅法和属性丢失了,⼀旦我们去调⽤派⽣类的⽅法和属性那就糟糕了,这就是对类继承关系和内存分配理解不清晰导致的。好在c++增加了static_cast和dynamic_cast运⽤于继承关系类间的强制转化
⼀、static_cast和dynamic_cast使⽤⽅式
static_cast< new_type >(expression)
dynamic_cast< new_type >(expression)
备注:new_type为⽬标数据类型,expression为原始数据类型变量或者表达式。
⼆、static_cast详解:
static_cast相当于传统的C语⾔⾥的强制转换,该运算符把expression转换为new_type类型,⽤来强迫隐式转换如non-const对象转为const对象,编译时检查,⽤于⾮多态的转换,可以转换指针及其他,但没有运⾏时类型检查来保证转换的安全性。它主要有如下⼏种⽤法:
①⽤于类层次结构中基类(⽗类)和派⽣类(⼦类)之间指针或引⽤的转换。
进⾏上⾏转换(把派⽣类的指针或引⽤转换成基类表⽰)是安全的;typec转dp
进⾏下⾏转换(把基类指针或引⽤转换成派⽣类表⽰)时,由于没有动态类型检查,所以是不安全的。
②⽤于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
③把空指针转换成⽬标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性
基本类型数据转换举例如下:
char a = 'a';
int b = static_cast<char>(a);//正确,将char型数据转换成int型数据
double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针
int e = 10;
const int f = static_cast<const int>(e);//正确,将int型数据转换成const int型数据
const int g = 20;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性
类上⾏和下⾏转换:
class Base
{};
class Derived : public Base
{}
Base* pB = new Base();
if(Derived* pD = static_cast<Derived*>(pB))
{}//下⾏转换是不安全的(坚决抵制这种⽅法)
Derived* pD = new Derived();
if(Base* pB = static_cast<Base*>(pD))
{}//上⾏转换是安全的
三、dynamic_cast详解:
转换⽅式:
dynamic_cast< type* >(e)
 type必须是⼀个类类型且必须是⼀个有效的指针
dynamic_cast< type& >(e)
type必须是⼀个类类型且必须是⼀个左值
dynamic_cast< type&& >(e)
type必须是⼀个类类型且必须是⼀个右值
e的类型必须符合以下三个条件中的任何⼀个:
1、e的类型是⽬标类型type的公有派⽣类
2、e的类型是⽬标type的共有基类
3、e的类型就是⽬标type的类型。
如果⼀条dynamic_cast语句的转换⽬标是指针类型并且失败了,则结果为0。如果转换⽬标是引⽤类型并且失败了,则dynamic_cast运算符将抛出⼀个std::bad_cast异常(该异常定义在typeinfo标准库头⽂件中)。e也可以是⼀个空指针,结果是所需类型的空指针。
dynamic_cast主要⽤于类层次间的上⾏转换和下⾏转换,还可以⽤于类之间的交叉转换(cross cast)。
在类层次间进⾏上⾏转换时,dynamic_cast和static_cast的效果是⼀样的;在进⾏下⾏转换时,dynamic_cast具有类型检查的功能,⽐static_cast更安全。dynamic_cast是唯⼀⽆法由旧式语法执⾏的动作,也是唯⼀可能耗费重⼤运⾏成本的转型动作。
(1)指针类型
举例,Base为包含⾄少⼀个虚函数的基类,Derived是Base的共有派⽣类,如果有⼀个指向Base的指针bp,我们可以在运⾏时将它转换成指向Derived的指针,代码如下:
if(Derived *dp = dynamic_cast<Derived *>(bp)){
//使⽤dp指向的Derived对象
}
else{
//使⽤bp指向的Base对象
}
值得注意的是,在上述代码中,if语句中定义了dp,这样做的好处是可以在⼀个操作中同时完成类型转换和条件检查两项任务。
(2)引⽤类型
因为不存在所谓空引⽤,所以引⽤类型的dynamic_cast转换与指针类型不同,在引⽤转换失败时,会抛出std::bad_cast异常,该异常定义在头⽂件typeinfo中。
void f(const Base &b){
try{
const Derived &d = dynamic_cast<const Base &>(b);
//使⽤b引⽤的Derived对象
}
catch(std::bad_cast){
//处理类型转换失败的情况
}
}
四、转换注意事项:
尽量少使⽤转型操作,尤其是dynamic_cast,耗时较⾼,会导致性能的下降,尽量使⽤其他⽅法替代。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。