dynamic_cast

基本用法
dynamic_cast可以获取目标对象的引用或指针:

  1. T1 obj;
  2. T2* pObj = dynamic_cast<T2*>(&obj);//转换为T2指针,失败返回NULL
  3. T2& refObj = dynamic_cast<T2&>(obj);//转换为T2引用,失败抛出bad_cast异常

多态类型
在使用时需要注意:被转换对象obj的类型T1必须是多态类型,即T1必须公有继承自其它类,或者T1拥有虚函数(继承或自定义)。若T1为非多态类型,使用dynamic_cast会报编译错误。下面的例子说明了哪些类属于多态类型,哪些类不是:

  1. //A为非多态类型
  2. class A{
  3. };
  4. //B为多态类型
  5. class B{
  6. public: virtual ~B(){}
  7. };
  8. //D为多态类型
  9. class D: public A{
  10. };
  11. //E为非多态类型
  12. class E : private A{
  13. };
  14. //F为多态类型
  15. class F : private B{
  16. }

横向转型
在多态类型间转换,分为3种类型:

  1. 子类向基类的向上转型(Up Cast)
  2. 基类向子类的向下转型(Down Cast)
  3. 横向转型(Cross Cast)

向上转型是多态的基础,需不要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用即可,当然dynamic_cast也支持向上转型,而其总是肯定成功的。而对于向下转型和横向转型来讲,其实对于dynamic_cast并没有任何区别,它们都属于能力查询。为了理解方便,我们不妨把dynamic_cast视为cross cast:

image.png

  1. class Shape {
  2. public: virtual ~Shape();
  3. virtual void draw() const = 0;
  4. };
  5. class Rollable {
  6. public: virtual ~Rollable();
  7. virtual void roll() = 0;
  8. };
  9. class Circle : public Shape, public Rollable {
  10. void draw() const;
  11. void roll();
  12. };
  13. class Square : public Shape {
  14. void draw() const;
  15. };

//横向转型失败
Shape pShape1 = new Square();
Rollable
pRollable1 = dynamic_cast(pShape2);//pRollable为NULL
//横向转型成功
Shape pShape2 = new Circle();
Rollable
pRollable2 = dynamic_cast(pShape2);//pRollable不为NULL

指针比较
接上面的例子,在我的机器上pShape2和pRollable2的值(所指向的地址)分别为:
pShape2: 0x0039A294, pRollable2:0x0039A290
说明dynamic_cast在进行转型的时候对不同多态类型设置了不同的偏移量。接下来的问题是
pRollable2 == pShape2
这个表达式应该返回什么呢?答案是:1,即指针比较相等。也许从C语言转到C++的朋友可能会感到困惑,因为在C语言中指针的比较只是值比较而已。显然,对于多态类型,C++编译器为==运算符做了更多的幕后工作来保证指针比较注重对象的同一性而非指针的值。至于实现细节涉及到C++对象模型,这是我还不甚熟悉的内容,故本文不再深入。

参考

https://www.cnblogs.com/weidagang2046/archive/2010/04/10/1709226.html