原則34:區(qū)分接口繼承和實現(xiàn)繼承

這個來源于需求,有的時候你只希望繼承接口,有的時候你希望既繼承接口又繼承實現(xiàn),并且還希望覆蓋父類中已有的方法。這個標題就來源于這個需求。
在這里作者舉了一個shape類的例子。這個shape類中有個純虛函數(shù),這使shape類成為一個抽象類,從而它不能擁有實例,而它的實現(xiàn)只能依靠它的子類來完成。例子中它的子類有兩個一個是矩形一個是橢圓形。這兩者都以public繼承了shape類,很顯然這必須要滿足IS-A原則。
在shape類中有3個函數(shù),它們是純虛函數(shù)draw、普通虛函數(shù)error、普通非虛函數(shù)objectID。
純虛函數(shù)的性質有二,1、它必須在子類中重新聲明一下,2、通常來講它在抽象類中沒有實現(xiàn)。那么這兩者結合在一塊說明了什么呢?它說明這個函數(shù)接口存在的意義就是讓你來繼承的。
另外,純虛函數(shù)通常是沒有定義的,這說明什么呢?這說明在抽象類中純虛函數(shù)可以有自己的實現(xiàn),只不過一般人家不寫,因為反正這是給別人去繼承的。這一點很重要。
那么虛函數(shù)存在的意義是什么呢?它通常是有一份實現(xiàn)的,并且這份實現(xiàn)是默認的,還有它也是用來被繼承的。因為凡是virtual的,都是一個virtual表,這個表里面都是指針,它們指向那些非virtual的函數(shù)。這就說明如果子類重寫了該virtual函數(shù),那么調用該子類的時候就使用這個重寫后的實現(xiàn)。否則,就調用那個默認的實現(xiàn)。
那如果有的時候子類并未明確提出它想要使用這個默認的實現(xiàn),同時它有沒有自己去實現(xiàn),這時候該咋辦呢?現(xiàn)總結一下問題吧,問題是你現(xiàn)在肯定是要繼承接口了,但是它那個默認的是實現(xiàn)你還不一定要。那就只能在父類中使用純虛擬函數(shù)了,然后在純虛擬函數(shù)中去掉用另外一個正常的成員函數(shù),這個正常的成員函數(shù)是其默認實現(xiàn)。
但要記住本原則的目標是要實現(xiàn)接口和實現(xiàn)的分離,通俗來講就是你要繼承接口的時候你就只繼承接口,你要使用默認的實現(xiàn)的時候就能使用默認的實現(xiàn),你要是不想使用默認的實現(xiàn)你就自己寫一個實現(xiàn)出來用。那么如何達到這個目的?其實很簡單,具體做法就是讓父類中的純虛函數(shù)擁有自己的一份實現(xiàn)代碼。因為純虛函數(shù)肯定要被繼承,但是它不強求你去掉用它的默認代碼,這就說明當你在子類中寫了一個函數(shù)聲明但不給出實現(xiàn)的時候,它不會去自動調用純虛函數(shù)的實現(xiàn)。而如果說你要使用純虛函數(shù)的實現(xiàn),那你可以使用類名進行限定,這樣就能調用純虛函數(shù)的實現(xiàn)代碼了。那么這樣的話,你只需要在子類的函數(shù)實現(xiàn)中通過類名指定父類中的純虛函數(shù)的實現(xiàn)即可。
下面只剩下父類中的那個普通成員函數(shù)沒有討論到了,就是那個objectID。那么這個普通的成員函數(shù)存在的意義是什么呢?其實就是無論你子類怎么變,我這個行為就是不變的,你子類直接用就可以了,也就是說一般來講它是不變的。
這里不得不再談談80-20法則。這個法則是什么意思呢?就是說程序執(zhí)行時間的80%要花在只占工程總量20%的代碼身上,而這個代碼表示的是邏輯的實現(xiàn)算法的設計上面,而由語言機制帶來的效率問題只占小部分,所以一般情況下,我們寫程序不要舍本逐末,只見樹木不見森林。
好了,現(xiàn)在總結一下作者的觀點:
1、對接口繼承和實現(xiàn)繼承要區(qū)別對待,在public繼承之下,父類接口總是要被子類繼承的;
2、純虛函數(shù)只是接口繼承;
3、非純虛函數(shù)既指定接口繼承也要繼承缺省實現(xiàn);
4、非virtual函數(shù)應該原封不動地繼承。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容