不能dynamic_cast侧身

Cannot dynamic_cast sideways

我偶然发现从派生到派生的横向转换 class 并发现了我的知识差距。直到现在,我一直生活在一个可以做到这一点的世界里。相反, std::bad_cast 被抛出。这是怎么回事?

#include <iostream>

class Base
{
protected:
    int x_;

public:
    Base(int x) : x_(x) {}
    virtual ~Base() = default;
    int x() const { return x_; }
    virtual void setX(int x) = 0;
};

class Editable : public Base // class implements setters
{
public:
    Editable(int x) : Base(x) {}
    void setX(int x) { x_ = x; }
};

class ReadOnly : public Base // class implements empty setters
{
public:
    ReadOnly(int x) : Base(x) {}
    void setX(int x) {}
};

int main()
{
    Editable editable(4);
    ReadOnly &readOnly = dynamic_cast<ReadOnly&>(editable); // std::bad_cast
}

这就是人们说dynamic_cast可以侧身施法的意思:

struct A { virtual ~A() = default; };
struct B { virtual ~B() = default; };
struct D : A, B {};

B* pb = new D();
A* pa = dynamic_cast<A*>(pb); // OK

即,如果指针指向从 AB 派生的东西,它允许您将 B* 转换为 A*。要使转换成功,仍然必须有一个 A 指针指向的子对象(或绑定到的引用,如果要转换为引用类型)。

在您的例子中,eEditable。那里的任何地方都没有 ReadOnly 子对象。所以转换失败。

你没有侧身施法。
您正在从一个派生的基础转换为另一个。

假设您的转换成功了,并且在 ReadOnly class.

中有一个名为 readOnlyInt 的 public int 成员

编译器如何执行readonly.readOnlyInt
铸造的 ReadOnly & 中没有 readOnlyInt 因为它实际上是 Editable.

横向转换涉及多个继承结构,看起来像这样:

class A {
    virtual ~A() {}
};

class B {
    virtual ~B() {}
};

class C : public A, public B {
};

int main() {
    B *b = new C();
    A *a = dymanic_cast<A *>(b);

    return 0;
}