天天看點

C++的重載(overload)與重寫(override)

C++的重載(overload)與重寫(override)

成員函數被重載的特征:

(1)相同的範圍(在同一個類中);

(2)函數名字相同;

(3)參數不同;

(4)virtual關鍵字可有可無。

重寫是指派生類函數重寫基類函數,是C++的多态的表現,特征是:

(1)不同的範圍(分别位于派生類與基類);

(3)參數相同;

(4)基類函數必須有virtual關鍵字。

示例中,函數Base::f(int)與Base::f(float)互相重載,而Base::g(void)被Derived::g(void)重寫。

C++的重載(overload)與重寫(override)
C++的重載(overload)與重寫(override)

令人迷惑的隐藏規則

本來僅僅差別重載與重寫并不算困難,但是C++的隐藏規則(遮蔽現象)使問題複雜性陡然增加。這裡“隐藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:

(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數将被隐藏。

(2)如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隐藏。

這種隐藏規則,不僅僅是表現在對成員函數上,對同名的data member也是如此。

示例程式中:

(1)函數Derived::f(float)重寫了Base::f(float)。

(2)函數Derived::g(int)隐藏了Base::g(float)。

(3)函數Derived::h(float)隐藏了Base::h(float)。

C++的重載(overload)與重寫(override)
C++的重載(overload)與重寫(override)

另一個關于虛函數很微妙的錯誤情況:參數相同,但是基類的函數是const的,派生類的函數卻不是。

C++的重載(overload)與重寫(override)
C++的重載(overload)與重寫(override)

(1)一個函數在基類申明一個virtual,那麼在所有的派生類都是是virtual的。

(2)一個函數在基類為普通函數,在派生類定義為virtual的函數稱為越位,函數行為依賴于指針/引用的類型,而不是實際對象的類型。

C++的重載(overload)與重寫(override)
C++的重載(overload)與重寫(override)

《Effective C++》條款: 決不要重新定義繼承而來的非虛函數。說明了不能重新定義繼承而來的非虛函數的理論依據是什麼。

以下摘自《Effective C++》:

公有繼承的含義是 "是一個","在一個類中聲明一個非虛函數實際上為這個類建立了一種特殊性上的不變性"。如果将這些分析套用到類B、類D和非虛成員函數B::mf,那麼:

(1)适用于B對象的一切也适用于D對象,因為每個D的對象 "是一個" B的對象。

(2)B的子類必須同時繼承mf的接口和實作,因為mf在B中是非虛函數。

那麼,如果D重新定義了mf,設計中就會産生沖突。如果D真的需要實作和B不同的mf,而且每個B的對象(無論怎麼特殊)也真的要使用B實作的mf,那麼每個D将不 "是一個" B。這種情況下,D不能從B公有繼承。相反,如果D真的必須從B公有繼承,而且D真的需要和B不同的mf的實作,那麼,mf就沒有為B反映出特殊性上的不變性。這種情況下,mf應該是虛函數。最後,如果每個D真的 "是一個" B,并且如果mf真的為B建立了特殊性上的不變性,那麼,D實際上就不需要重新定義mf,也就決不能這樣做。

不管采用上面的哪一種論據都可以得出這樣的結論:任何條件下都要禁止重新定義繼承而來的非虛函數。

    本文轉自阿凡盧部落格園部落格,原文連結:http://www.cnblogs.com/luxiaoxun/archive/2012/08/09/2630751.html,如需轉載請自行聯系原作者

下一篇: onblur 事件

繼續閱讀