dynamic_cast运算符的主要用途:将基类的指针或引用安全地转换成派生类的指针或引用,并用派生类的指针或引用调用非虚函数。如果是基类指针或引用调用的是派生类虚函数无需转换就能在运行时调用派生类的虚函数。
前提条件:当我们将dynamic_cast用于某种类型的指针或引用时,只有该类型含有虚函数时,才能进行这种转换。否则,编译器会报错!
dynamic_cast运算符的调用形式如下所示:
dynamic_cast<type*>(e) //e是指针
dynamic_cast<type&>(e) //e是左值
dynamic_cast<type&&>(e)//e是右值
e能成功转换为type*类型的情况有三种:
1)e的类型是目标type的公有派生类:派生类向基类转换一定会成功。
2)基类向派生类转换,e的类型是目标type的基类,当e是指针指向派生类对象,或者基类引用引用派生类对象时,类型转换才会成功,当e指向基类对象,试图转换为派生类对象时,转换失败。
3)e的类型就是type的类型时,一定会转换成功。
定义如下基类和派生类:
#include<string>
#include<iostream>
usingnamespacestd;
classBase{
public:
Base():str(nullptr)
{}
Base(strings):str(s)
{}
virtualvoidprint()
{
cout<<str<<" ";
}
private:
stringstr;
};
classDerived:publicBase
{
Derived()
{}
Derived(strings,inti):Base(s),ival(i)
{}
voidprint()
{
Base::print();
cout<<ival<<endl;
}
voidprint_ival()
{
cout<<"仅输出ival的值:"<<ival<<endl;
}
private:
intival;
};
一、指针类型的dynamic_cast
如果一条dynamic_cast语句的转换目标是指针类型并且转换失败了,会返回一个空指针,则判断条件为0,即为false;如果转换成功,指针为非空,则判断条件为非零,即true。
例如:
Base base(“liu”);
Derived de(“wang”,23);
Base*pb=&de;
则:Derived *pd=dynamic_cast<Derived*>(pb)会转换成功
可以用于以下的条件判断中:
//这样做可以确保类型转换和条件检查在同一条表达式中完成
if(Derived*pd=dynamic_cast<Derived*>(pb))
{
//使用pd指向Derived对象
pd->print_ival();//调用派生类的非虚函数
}
else
{
//使用pb指向额Base对象
……
}
NOTE:我们可以对一个空指针执行dynamic_cast,结果是所需类型的空指针。
二、引用类型的dynamic_cast
引用类型的dynamic_cast和指针类型的dynamic_cast在表示错误发生的方式上略有不同。因为不存在空引用,所以对于引用类型来说无法使用与指针类型完全相同的错误报告策略。当对引用类型转换失败时,程序抛出一个名为std::bad_cast的异常,该异常定义在typeinfo标准库头文件中。
可按照如下的形式改写之前的程序,令其使用引用类型。
void f(const Base &b)
{
try{
const Derived &d=dynamic_cast<Derived&>(b);
} catch(bad_cast){
//处理类型转换失败的情况
}
}