2012-11-11 131 views
3

對不起,這是如此做作,但它涉及到一個作業問題。我明白爲什麼一切都會發生,除了我評論的那一行。有人可以向我解釋爲什麼C++正在做它正在做的事情嗎?C++繼承和方法重載混淆

感謝

#include <iostream> 

using namespace std; 

class X0 {}; 
class X1: public X0 {}; 
class X2: public X1 {}; 

class Y1 
{ 
public: 
    virtual void f(int v)  { cout << "Y1(int)" << endl; } 
    virtual void f(const X0 *x) { cout << "Y1(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y1(X1)" << endl; } 
}; 

class Y2: public Y1 
{ 
public: 
    virtual void f(const X0 *x) { cout << "Y2(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y2(X1)" << endl; } 
    virtual void f(const X2 *x) { cout << "Y2(X2)" << endl; } 
}; 

int main(int argc, char * argv[]) 
{ 
    X2 x2; X2 *X2Pointer = &x2; 
    Y2 y2; Y1 *Y1Pointer = &y2; 

    cout << "What is about to happen?" << endl; 
    //Y1 pointer points to a Y2 object. 
    //The Y2 class, upon being given an X2 pointer, should print Y2(X2) 
    Y1Pointer->f(X2Pointer); 
    cout << "Why did I just print Y2(X1)" << endl; 
    return 0; 
} 
+1

C++沒有做任何事情。它是你這樣做的人 –

+1

這幾乎是一個最小例子的*相反*。我們不需要演示你*做什麼*瞭解 - 只是你不知道的一個例子。 –

回答

3

Y1公開這些存在的f()超載:

class Y1: public Y0 { 
public: 
    virtual void f(int v)  { cout << "Y1(int)" << endl; } 
    virtual void f(const X0 *x) { cout << "Y1(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y1(X1)" << endl; } 
    // ... 
}; 

其他所有方法稱爲f()Y0繼承是隱藏的。也就是說,當你調用

Y1Pointer->f(X2Pointer); 

的編譯器上的f()的三個重載過載的分辨率和得出的結論是f(const X1*)是最好的搭配並調用此函數。事實證明,這是一個virtual函數,被Y2覆蓋,因此它調用Y2::f(const X1*)

+0

糾正我,如果我錯了,但我收集的是這樣的: 編譯器查看指針類型,它是Y1。所以它進入Y1類,並找出哪個f()最匹配。然後使用Y1指向的對象的類型Y2,並調用Y2中與Y1中決定的簽名具有相同簽名的方法? –

+0

@ user1137940:是的,如果第一步發現了「虛擬」功能,就會發生這種情況。我想這也是我在我的回答中所說的。 –

1

重載分辨率是根據所涉及的靜態類型確定的。

Y1Pointer->f(X2Pointer)火柴Y1::f(const X1 *x),因爲靜態類型的Y1PointerY1*,所以Y1::f(const X1 *x)是到f調用使用X2*參數的最佳匹配。

Y1::f(const X1 *x)是虛擬的,所以調用的實際功能是由動態類型決定的。 Y1Pointer指向一個Y2,因此Y2版本的f(const X1 *x)被調用。

1

Y1類沒有超載消耗X2 *。函數調用Y1Pointer->f(X2Pointer)的最佳匹配是Y1::f(X1 const *)。事實上,Y1Pointer點比Y1派生的實際對象無關緊要,因爲它與選擇的過載無關。

0

正如其他提到的問題是功能隱藏。但是你可以做的是寫在Y1行using Y0::f;裏面以得到你想要的結果。