C++11中引入了一些新的类型转换操作符,我们来看看dynamic_cast的使用。
首先,让我们考虑一下:在什么场景下我们希望使用dynamic_cast呢?
#include <iostream>
class Base
{
public:
virtual void print()
{
std::cout << "Base print" << std::endl;
}
void work()
{
std::cout << "Base do work..." << std::endl;
}
};
class Derived : public Base
{
public:
virtual void print()
{
std::cout << "Derived print!" << std::endl;
}
void work()
{
std::cout << "Derived do work..." << std::endl;
}
};
int main()
{
Base* pBase = new Derived();
pBase->print();
pBase->work();
getchar();
return 0;
}
运行结果:
Derived print!
Base do work...
分析结果:print()是虚函数,在运行时的类型来决定运行结果;而work()函数不是虚函数,只是类的普通成员函数,在编译期间决定。所以调用的Base::work()函数。
如果我们希望通过指针调用Derived::work(),该怎么做呢?
使用dynamic_cast
Derived* pDerived = dynamic_cast<Derived*>(pBase);
语法
dynamic_cast < 新类型 > ( 表达式 )
若转型成功,则 dynamic_cast 返回 新类型 类型的值。若转型失败且 新类型 是指针类型,则它返回该类型的空指针。若转型失败且 新类型 是引用类型,则它抛出与类型 std::bad_cast 的处理块匹配的异常。
为了理解官方文档这段话,我写了下面的代码,在刚才的代码上修改,只修改了main函数中的内容:
int main()
{
Base* pBase = new Derived();
pBase->print();
pBase->work();
Derived* pDerived = dynamic_cast<Derived*>(pBase); //向下转换成功,成功返回Derived*
if (pDerived != nullptr)
{
pDerived->print();
pDerived->work();
}
Base *pRealBase = new Base();
pDerived = dynamic_cast<Derived*>(pRealBase); //向下转换失败,返回nullptr指针
if (pDerived != nullptr)
{
pDerived->print();
pDerived->work();
}
Base base;
Base& refBase = base;
try
{
Derived refDerived = dynamic_cast<Derived&>(refBase);
}
catch (const std::exception& e)
{
std::cout << "first try failed, reason: " << e.what() << std::endl;
}
Derived derived;
Base& refBaseNew = derived;
try
{
Derived refDerived = dynamic_cast<Derived&>(refBaseNew);
}
catch (const std::exception& e)
{
std::cout << "second try failed: reason: " << e.what() << std::endl;
}
getchar();
return 0;
}
运行结果:
Derived print!
Base do work...
Derived print!
Derived do work...
first try failed, reason: Bad dynamic_cast!
小结:
dynamic_cast < new_type > ( expression )
在执行向下类型转换(基类向子类转换,叫“向下类型转换”),如果expression实际指向的类型与new_type一致,转换才能成功,否则转换失败。
dynamic_cast存在的问题:
dynamic_cast最大的问题在于效率,特别是继承体系特别深时。可以尝试用static_cast来替代dynamic_cast的使用。
对于效率问题,这篇博文里讲的比较好:https://blog.csdn.net/debugconsole/article/details/9379627
为什么说不要使用 dynamic_cast,需要运行时确定类型信息,说明设计有缺陷?
参考:https://blog.csdn.net/u011333734/article/details/81329523