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