Dynamic_cast 未显示正确的对象类型

Dynamic_cast not showing the right object type

我花了很多时间试图弄清楚为什么我的代码在 运行 之后显示 "Derived3" 而我根本无法理解它。根据我在这里阅读的许多帖子,dynamic_cast 应该以某种方式说明指针(在本例中为 b)是否(在本例中)是 Derived2。然而,它通过了条件,当它应该打印出 Derived2 class 的 display() 函数时,它奇怪地显示了 Derived3 class 的那个。我只是想知道为什么程序显示 "Derived 3" 而不是不显示任何内容,因为 b 指针显然没有指向 Derived2 对象。

#include <iostream>

using namespace std;

class Base
{
    int b;
    public:
    virtual void display()
    {
        cout<<"Base"<<endl;
    }
};

class Derived: virtual public Base{
public:
    void display()
    {
        cout<<"Derived"<<endl;
    }
};

class Derived2: virtual public Base{
public:
    void display()
    {
        cout<<"Derived 2"<<endl;
    }
};

class Derived3:public Derived,public Derived2{
public:
    void display()
    {
        cout<<"Derived 3"<<endl;
    }
};

int main()
{
    Base *b = new Derived3();
    Derived2 *aux = dynamic_cast<Derived2*>(b);
    if(aux)
    {
        aux->display();
    }

    return 0;
}

不过,稍微编辑一下代码后,它就可以正常工作了。

#include <iostream>

using namespace std;

class Base
{
    int b;
    public:
    virtual void display()
    {
        cout<<"Base"<<endl;
    }
};

class Derived: public Base{
public:
    void display()
    {
        cout<<"Derived"<<endl;
    }
};

class Derived2: public Base{
public:
    void display()
    {
        cout<<"Derived 2"<<endl;
    }
};

class Derived3:public Base{
public:
    void display()
    {
        cout<<"Derived 3"<<endl;
    }
};

int main()
{
    Base *b = new Derived3();
    Derived2 *aux = dynamic_cast<Derived2*>(b);
    if(aux)
    {
        aux->display();
    }

    return 0;
}

继承是一种"Is-a"关系。

每个Derived既是Derived又是Base。通过这种模式,每个 Derived3 同时是一个 Derived3、一个 Derived2、一个 Derived 和一个 Base

因此,该转换失败是没有意义的。

输出最终是对 Derived2* 的普通虚函数调用的结果。这与最简单的继承示例没有什么不同,就像这个片段:

#include <iostream>

struct A {
    virtual void fun() const {
        std::cout << 'A';
    }
};

struct B : A {
    void fun() const {
        std::cout << 'B';
    }
};

int main () {
    const A &a = B();
    a.fun();            // prints 'B'
}

如果您有指向某个基 class 的指针或引用,则虚函数调用将解析为调用它的对象的实际类型。在你的例子中,这是一个指向 Derived3 类型的子 class 的 Derived2*,因此在后者中查找该函数。

记住 dynamic_cast 只改变指针的类型,而不是它指向的对象的类型!

However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class.

那是因为动态调度。请记住 display() 被声明为 virtual 成员函数。它仍然是所有派生的 类.

virtual 成员函数

即使您将指针从 Base* 转换为 Derived*,底层对象仍然是 Derived3。因此,动态调度机制调用 Derived3::display().

Derived3::display() 也将被调用,如果你使用:

Base *b = new Derived3();
b->display();