在一次應聘過程中,負責技術的招聘人員提出了乙個實際開發中遇到的問題:
class base
;class derive: public base
};結果編譯卻發現錯誤。他想知道是怎麼回事。
當時怎麼看怎麼像函式過載(公有繼承嘛),似乎沒什麼問題呀,只好說不知道。後來終於在 effective c++ 2nd 中找到了答案。
item37:決不要重新定義繼承而來的非虛函式
對於上面的derive公有繼承於base,那麼
1、適用於base物件的一切也適用於derive物件,因為每個derive的物件 "是乙個" base的物件。
2、base的子類必須同時繼承函式(func)的介面和實現,因為函式(func)在base中是非虛函式。
那麼,如果derive重新定義了函式(func),設計中就會產生矛盾。如果derive真的需要實現和base不同的函式(func),而且每個base的物件 ---- 無論怎麼特殊 ---- 也真的要使用base實現的函式(func),那麼,每個derive將不 "是乙個" base。這種情況下,derive不能從base公有繼承。相反,如果derive真的必須從base公有繼承,而且derive真的需要和base不同的函式(func)的實現,那麼,函式(func)就沒有為base反映出特殊性上的不變性。這種情況下,函式(func)應該是虛函式。最後,如果每個derive真的 "是乙個" base,並且如果函式(func)真的為base建立了特殊性上的不變性,那麼,derive實際上就不需要重新定義函式(func),也就決不能這樣做。
因此,effective c++ 2nd得出結論——不管採用上面的哪一種論據都可以得出這樣的結論:任何條件下都要禁止重新定義繼承而來的非虛函式。
決不要重新定義繼承而來的非虛函式
有兩種方法來看待這個問題 理論的方法和實踐的方法。讓我們先從實踐的方法開始。畢竟,理論家一般都很耐心。假設類d公有繼承於類b,並且類b中定義了乙個公有成員函式mf。mf的引數和返回型別不重要,所以假設都為void。換句話說,我這麼寫 class b class d public b 甚至對b,d或m...
條款37 決不要重新定義繼承而來的非虛函式
class b class d public b 甚至對b,d或mf一無所知,也可以定義乙個型別d的物件x,d x x是型別d的乙個物件 那麼,如果發現這麼做 b pb x 得到x的指標 pb mf 通過指標呼叫mf 和下面這麼做的執行行為不一樣 d pd x 得到x的指標 pd mf 通過指標呼叫...
不要重新定義繼承來的非虛函式
effective c item 36 class b class d public b 對於這個繼承體系,有這樣的 d x b pb x pb foo test b d pd x pd foo test d驚訝的發現,兩個語句的行為不一樣.兩者所呼叫的函式相同,物件也相同,因此行為也應該相同 但是...