2017-04-02 88 views
1

請看下面的代碼。爲什麼static_cast<D2&>(m).f()cout << static_cast<B&>(m).f()的輸出是33,而不是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

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

2

你的對象是M一個實例,並鑄造基地引用類型沒有變化那。虛擬函數的重點在於,當您在基指針或引用上調用某個函數時,它將轉到派生實現。