2013-03-01 30 views
-3

好吧,所以我知道有很多多態線程在飛行,但我還沒有遇到這種情況。C++中的多態性

class Base { 
public: 
    virtual void method1() { 
     cout << "BaseMethod1" << endl; 
    } 

    void method2() { 
     cout << "BaseMethod2" << endl; 
    } 
}; 

class Derive: public Base { 
public: 
    void method1() { 
     cout << "DeriveMethod1" << endl; 
     method2(); 
    } 

    void method2() { 
     cout << "DeriveMethod2" << endl; 
    } 
}; 

int main() { 
    Base* p = new Derive(); 
    p->method1(); 
} 

什麼讓我跳起來是派生類中的method1調用method2。那麼,由於基類中的方法2沒有被聲明爲虛擬的,哪種方法2?

提前致謝!

+3

你試過了嗎? – Pubby 2013-03-01 04:55:15

+2

'method2()'括號丟失,如果我沒有錯 – 2013-03-01 04:55:51

+1

@Pubby嘗試的東西不一定會導致C++的啓發。事實上,如果發生未定義的行爲,它會導致危險的虛假安全感。 – Antimony 2013-03-01 04:56:31

回答

4

由於Base::method1()被宣告爲private,所涉及的代碼將不會被編譯。 它需要是public才能從main調用。


Derived::method1()隱含virtual即使沒有標記爲virtual。所以thisDerived::method1()指向一個Dervied對象,在這個範圍內編譯器只能看到Derived::method2()。因此Derived::method2()將被調用。派生類中的方法在基類中隱藏了相同的命名方法。


良好閱讀:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

1

它將使用Derive::method2()姓名查找(在身體的Derive::method1())從類本身開始。

2

你不經常看到這種模式的主要原因是它實際上是一種反模式。

Derived方法將被調用,因爲您使用Derived對象引用(this)調用它。如果您使用Base類引用調用它,您將獲得Base方法。

如果你重新聲明瞭一個非虛方法,你隱藏了基本方法並打破了多態性。

+0

對於幾個優點(特別是'this'的重要性)+1,但關於「重新聲明一個非虛擬方法[是]打破多態性」 - 這有點曲調:對象可能繼續通過基類參考/指針非常好 - 按照Liskov替換原則 - 或者甚至可能有必要不要讓某些函數虛擬以避免破壞原理(例如,根據Base方法文檔不可修復的派生類序列化方法)。沒有中斷,但很脆弱(例如,難以轉換爲編譯時多態)。 – 2013-03-01 05:59:46

+0

好點。規則幾乎總是有例外。我傾向於堅持這個特別的規則,因爲它減少了在大代碼庫中出錯的可能性。這與人們所期望的矛盾。我想你可以說它誇大了多態性,因爲現在你正在根據你如何引用它來創建一個擁有多種形式的對象:P。 – 2013-03-01 06:23:04