2017-04-02 13 views
1

以下のコードを見てください。 static_cast<D2&>(m).f()cout << static_cast<B&>(m).f()の出力がで、21でないのはなぜですか?仮想継承 - なぜこの出力

struct B { 
    virtual int f() {return 1;} 
}; 
struct D1 : virtual public B { 
    virtual int f(){return 2;} 
}; 
struct D2 : virtual public B{}; 
struct M : public D1, public D2 { 
    virtual int f() {return 3;} 
}; 

int main(){ 
    M m; 
    cout << static_cast<D2&>(m).f(); 
    cout << static_cast<B&>(m).f(); 
    return 0; 
} 
+0

「21」はなぜですか?仮想関数の全体のポイントは、関数呼び出しがその静的型ではなくオブジェクトの動的型にディスパッチされることです。 – Quentin

+0

ここで仮想*継承*、仮想*関数のみ*は必要ないことを理解していますか?この場合の仮想継承は通常の継承と変わらない。 – HolyBlackCat

答えて

3

それは仮想派遣の全体のポイントだからです:派遣の対象は、呼び出し式の静的にノミネートされたオブジェクトが含まれているほとんどの派生オブジェクトの動的タイプによって決定されます。

あなたはあなたが関数呼び出しを修飾することによってそれをバイパスすることができ、仮想ディスパッチをしたくない場合:

m.B::f(); 
m.D1::f(); 
m.D2::f(); 
+0

[デモ](https://wandbox.org/permlink/X9xIh2ivTSniCni5) –

2

あなたのオブジェクトがMのインスタンスであり、かつ基本参照型にキャストすると、変更されません。それ。仮想関数の全体のポイントは、基本ポインタまたは参照で関数を呼び出すと、導出された実装に移動することです。