为什么我不能在多重继承期间“侧向”动态广播?

时间:2011-01-09 19:56:44

标签: c++ inheritance constructor dynamic-cast object-lifetime

以下代码抛出std :: bad_cast

struct Foo {
    void foo () {}
};

struct Bar {
    Bar () {
        dynamic_cast <Foo &> (*this) .foo ();
    }
    virtual ~ Bar () {}
};

struct Baz : public Foo, public Bar {
};

int main ()
{
    Baz b;
}

我记得曾经读过一次dynamic_cast如何进行实现性能权衡因为“它遍历完整的继承网格”才能正确评估。编译器需要做的是先进行再次向下再次向下运行。

是否可以进行上述工作或是否需要添加 virtual Foo* Bar::as_foo()=0;

4 个答案:

答案 0 :(得分:7)

Foo中没有虚函数,因此dynamic_cast非常有必要失败。需要有一个虚拟功能。在施工期间这样做也是一个坏主意,因为您将遇到施工订单问题。

答案 1 :(得分:2)

假设Bar应该继承自Foo(当前示例中没有),您在此处看到的问题通常被称为diamond problem。您要使用哪个版本的fooBar::foo()Foo::foo()?您将需要指定虚拟继承:

struct Foo{
    ~virtual Foo(){}
     void foo(){}
};

struct Bar : virtual public Foo

struct Baz : virtual public Foo, public Bar

让它知道应该只存在一种foo()。因此,virtual inheritance用于在构造函数中调用foo()的调用。

编辑:

要明确的是,我假设您希望Bar继承Foo。如果你的代码中没有那个,那么这就是错误的转换错误的原因。 Bar没有继承层次结构可以遍历到Foo。此外,现代编译器甚至不应该在没有虚拟继承的情况下进行编译,但是某些遗留编译器很乐意@#$#$ up。

如果我要评论另一个答案,我最好按照自己的答案进行评论!

答案 2 :(得分:1)

你的例子中有一些问题,也许是偶然的?

Bar不会从Foo继承,所以它不能在Bar的构造函数中转换为Foo。它们也不共享公共继承父级,因此不能在彼此之间(侧向)进行转换。你可能想要的是:

struct withFoo {
    virtual void foo () {}
    virtual ~withFoo() {}
};

struct Foo : public virtual withFoo {
};

struct Bar : public virtual withFoo {
    Bar () {
        foo();  // no need to cast!
    }
};

struct Baz : public Foo, public Bar {
};

int main ()
{
    Baz b;
    b.foo(); // because of virtual inheritance from withFoo, there is no ambiguity here 
}

希望这有帮助!如果您需要澄清,请询问!

答案 3 :(得分:0)

构建Baz涉及构建其基础,其中一个是Bar。即使最终的Baz应该是,Baz的Bar基地也不能投入Foo。