條款44: 說你想說的;理解你所說的
在本章關于 "繼承和面向對象設計" 的簡介中,我曾強調,理解不同的面向對象構件在C++中的含義十分重要。這和僅僅知道C++語言的規則有很大的不同。例如,C++規則說,如果類D從類B公有繼承,從D的指針到B的指針就有一個標準轉換;B的公有成員函數將被繼承為D的公有成員函數,等等。這些規則都是正確的,但在將設計思想轉化為C++的過程中,它們起不到任何作用。相反,你需要知道,公有繼承意味著 "是一個",如果D從B公有繼承,類型D的每一個對象也 "是一個" 類型B的對象。因而,如果想在設計中表示 "是一個",就自然會想到使用公有繼承。
"說出你想說的" 只是成功的一半。事情的另一面是 "理解你所說的",這一點同樣重要。例如,將成員函數聲明為非虛函數會給子類帶來限制,如果沒有認識到這一點就隨便這樣做將是不負責任的行為 ---- 除非你完全是有意這么做。聲明一個非虛成員函數,你實際上是在說這個函數表示了一種特殊性上的不變性;如果不明白這一點,將會給程序帶來災難。
公有繼承和 "是一個" 的等價性,以及非虛成員函數和 "特殊性上的不變性" 的等價性,是C++構件如何和設計思想相對應的例子。下面的列表總結了這些對應關系中最重要的幾個。
? 共同的基類意味著共同的特性。如果類D1和類D2都把類B聲明為基類,D1和D2將從B繼承共同的數據成員和/或共同的成員函數。見條款43。
? 公有繼承意味著 "是一個"。如果類D公有繼承于類B,類型D的每一個對象也是一個類型B的對象,但反過來不成立。見條款35。
? 私有繼承意味著 "用...來實現"。如果類D私有繼承于類B,類型D的對象只不過是用類型B的對象來實現而已;類型B和類型D的對象之間不存在概念上的關系。見條款42。
? 分層意味著 "有一個" 或 "用...來實現"。如果類A包含一個類型B的數據成員,類型A的對象要么具有一個類型為B的部件,要么在實現中使用了類型B的對象。見條款40。
下面的對應關系只適用于公有繼承的情況:
? 純虛函數意味著僅僅繼承函數的接口。如果類C聲明了一個純虛函數mf,C的子類必須繼承mf的接口,C的具體子類必須為之提供它們自己的實現。見條款36。
? 簡單虛函數意味著繼承函數的接口加上一個缺省實現。如果類C聲明了一個簡單(非純)虛函數mf,C的子類必須繼承mf的接口;如果需要的話,還可以繼承一個缺省實現。見條款36。
? 非虛函數意味著繼承函數的接口加上一個強制實現。如果類C聲明了一個非虛函數mf,C的子類必須同時繼承mf的接口和實現。實際上,mf定義了C的 "特殊性上的不變性"。見條款36。
新聞熱點
疑難解答
圖片精選