2

次のコードは 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

4 に答える 4

7

Foo には仮想関数がないため、dynamic_cast は完全に失敗する義務があります。仮想関数が必要です。建設順序の問題が発生するため、建設中にそうするのも悪い考えです.

于 2011-01-09T20:32:11.337 に答える
2

それが継承する必要があると仮定すると(現在の例でBarは継承されFooません)、ここで表示される問題は一般に菱形継承問題と呼ばれます。どちらのバージョンfooを使用しますか、Bar::foo()またはFoo::foo()?仮想継承を指定する必要があります。

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

struct Bar : virtual public Foo

struct Baz : virtual public Foo, public Bar

のタイプは1つだけ存在する必要があることを通知しfoo()ます。したがって、仮想継承foo()は、コンストラクター内でへの呼び出しを呼び出すために使用されます。

編集:

Barそして明確にするために、私はあなたがから継承したいと思っていると仮定していますFoo。コードにそれがない場合は、それが不良キャストエラーの原因です。Barに到達するためにトラバースするための継承階層はありませんFoo。また、最新のコンパイラは仮想継承なしでコンパイルするべきではありませんが、特定のレガシーコンパイラは喜んでそれを@#$#$アップします。

また、別の回答についてコメントする場合は、自分の回答をフォローすることをお勧めします。

于 2011-01-09T20:00:24.977 に答える
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 
}

お役に立てれば!説明が必要な場合は、お尋ねください。

于 2011-01-09T20:11:59.287 に答える
0

バズの構築にはそのベースの構築が含まれ、そのうちの1つがバーです。バズのバーベースは、最終的なバズがキャスト可能であっても、フーにキャスト可能ではありません。

于 2011-01-09T21:24:50.027 に答える