在面向对象程序设计中,有时咱们须要在运行时查询一个对象是否能做为某种多态类型使用。与Java的instanceof,以及C#的as、is运算符相似,C++提供了dynamic_cast
函数用于动态转型。相比C风格的强制类型转换和C++ reinterpret_cast
,dynamic_cast
提供了类型安全检查,是一种基于能力查询(Capability Query)的转换,因此在多态类型间进行转换更提倡采用dynamic_cast
。本文主要介绍dynamic_cast
的意义,用法和注意事项。安全
基本用法函数
dynamic_cast
能够获取目标对象的引用或指针:设计
T1 obj; T2* pObj = dynamic_cast<T2*>(&obj); //转换为T2指针,失败返回NULL T2& refObj = dynamic_cast<T2&>(obj); //转换为T2引用,失败抛出bad_cast异常
多态类型指针
在使用时须要注意:被转换对象obj的类型T1
必须是多态类型,即T1
必须公有继承自其它类,或者T1
拥有虚函数(继承或自定义)。若T1
为非多态类型,使用dynamic_cast
会报编译错误。下面的例子说明了哪些类属于多态类型,哪些类不是:code
//A为非多态类型 class A{ }; //B为多态类型 class B{ public: virtual ~B(){} }; //D为多态类型 class D: public A{ }; //E为非多态类型 class E : private A{ }; //F为多态类型 class F : private B{ };
横向转型对象
在多态类型间转换,分为3种类型:
1.子类向基类的向上转型(Up Cast)
2.基类向子类的向下转型(Down Cast)
3.横向转型(Cross Cast)继承
向上转型是多态的基础,需不要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用便可,固然dynamic_cast
也支持向上转型,而其老是确定成功的。而对于向下转型和横向转型来说,其实对于dynamic_cast
并无任何区别,它们都属于能力查询。为了理解方便,咱们不妨把dynamic_cast
视为cross cast:it
class Shape { public: virtual ~Shape(); virtual void draw() const = 0; }; class Rollable { public: virtual ~Rollable(); virtual void roll() = 0; }; class Circle : public Shape, public Rollable { void draw() const; void roll(); }; class Square : public Shape { void draw() const; }; //横向转型失败 Shape *pShape1 = new Square(); Rollable *pRollable1 = dynamic_cast<Rollable*>(pShape2);//pRollable为NULL //横向转型成功 Shape *pShape2 = new Circle(); Rollable *pRollable2 = dynamic_cast<Rollable*>(pShape2);//pRollable不为NULL
指针比较编译
接上面的例子,在个人机器上pShape2
和pRollable2
的值(所指向的地址)分别为: pShape2: 0x0039A294
, pRollable2:0x0039A290
ast
说明dynamic_cast
在进行转型的时候对不一样多态类型设置了不一样的偏移量。接下来的问题是 pRollable2 == pShape2