关于动态转换和钻石继承

问题描述

我截断了以下代码

#include <iostream>
#include <typeinfo>
using namespace std;


class B{
int i;
public:
    B(){i = 1;}

virtual int get_i(){return i;}

};

class D: virtual public B{
    int j;
public:
    D(){j = 2;}
    int get_i(){return B::get_i() + j;}
};

class D2: virtual public B{
    int j2;
public:
    int get_i(){return B::get_i() + j2;}
};


class MM: public D,public  D2{
    int x;
public:
    MM(){
        x = D::get_i() + D2::get_i();
    }
    int get_i(){return x;}
};

int main(){
    B* o = new MM();
    cout << o->get_i() << "\n";
    MM* p = dynamic_cast<MM*>(o);
    if(p) cout << p->get_i() << "\n";
    D* p2 = dynamic_cast<D*>(o); /// Why does this dynamic_cast not return NULL?
    if(p2)
        cout << p2->get_i() << "\n";
}

The output will be:

我的问题是:为什么标记行上的dynamic_cast会成功?所以,如果我有这样的层次结构:

class Grandpa{...};
class Dad : public Grandpa{...};
class Son: public Dad{...};

当然了

Grandpa* grandpa = new Son();

没问题。

以下dynamic_cast

Dad* dad = dynamic_cast<Dad*>(grandpa);

总是成功?

这在某种程度上是合乎逻辑的,只要 Dad 指针始终可以指向 Son 对象,但我以前从未见过这种情况,我想确保我可以将其视为一般规则。

解决方法

为什么标记行上的dynamic_cast会成功?

因为对象的动态类型有一个 D 基。

将下面的dynamic_cast:

Dad* dad = dynamic_cast<Dad*>(grandpa);

总是成功?

鉴于 Grandpa* grandpa = new Son(); 的前提,是的,它会成功。

但在其他情况下不会成功,例如:

Grandpa gp;
Grandpa* grandpa = &gp;
Dad* dad = dynamic_cast<Dad*>(grandpa); // is null
,

是的,只要超类类型指针所指向的对象确实是您尝试强制转换的类型的对象,dynamic_cast 就会成功。如果它不是那种类型的对象,那么 otoh,dynamic_cast 将返回一个空指针。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...