dynamic_cast
static_cast可以实现子类到基类的安全转换,但是不能实现基类到子类的安全转换,那么如果想实现基类到子类的安全转换应该怎么处理呢?嗯是用dynamic_cast类型转换:
注意:
上行转换(子类到基类)是安全的,并且static_cast dynamic_cast是等效的
下行转换(基类到子类)static_cast转换是不安全的但是dynamic_cast转换是安全的
dynamic_cast被用来执行从基类到子类的安全转换,转换的类类型(基类)必须有虚函数,否则不能使用dynamic_cast
dynamic_cast<type-id>(expression)
如果type-id是void*类型,那么是expression类型。
如果type-id是非void*类型,那么运行时检查指向 expression 的对象能否转换为指向 type-id 类型的对象。
dynamic_cast指针例子:
class employee{
public:
virtual int salary();
};
class manager:public employee{
public:
int salary();
};
class programmer:public employee{
public:
int salary();
int bonus();
};
mytest(employee* pe){
//如果pe指向的是programmer类型的对象,则转换成功。否则,失败,结果为0。
programmer *pm = dynamic_cast<programmer*>(pe);
if(pm){//在使用pm之前必须使用if语句来判断是否转换成功
//可以用pm调用programmer::bonus()
}
else{
//只能使用employee的成员的虚函数。
}
}
因为存在空指针,所以mytest中可以使用if(pm)来判断转换是否有效。但是不存在空引用,因此不能比较dynamic_cast的结果是否为0来判断引用转换成功与否,但是会抛出bad_cast的异常。
mytest(employee& re){
try{
programmer& em = dynamic_cast<programmer&>(re);
//用em调用bonus;
}
catch(std:: bad_cast)
{
//使用employee的成员函数
}
}
例子总结:
1:
class A{};
class B{};
void func(){
A* pa=new A;
B* pb=new B;
void* pv=dynamic_cast<void*>(pa);
//pv就是一个A类型的对象了
......
pv=dynamic_cast<void*>(pb);
//pv就是一个B类型的对象了
......
}
2:
class B{};
class D:public B{};
void func(){
B* pb=new D;
B* pb2=new B;
D* pd=dynamic_cast<D*>(pb);//ok 转换成功,pd是一个指向D的指针
D* pd2=dynamic_cast<D*>(pb2);//转换失败但是编译通过,因为pd2指向的是null
}
为什么基类向子类转换会转换失败呢?因为基类向子类转换有可能会出现二义性。
另外:
dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
class A{
public:
int m_iNum;
virtual void f(){}
};
class B:public A{
};
class D:public A{
};
void foo(){
B *pb = new B;
pb->m_iNum = 100;
D *pd1 = static_cast<D*>(pb); //compile error
D *pd2 = dynamic_cast<D*>(pb); //pd2 is NULL
delete pb;
}
在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。