C++筆記三(面向對象編程上)

十一 組合和繼承

OOD(Object Oriented Design)
(1)基于對象:單一類的寫法;
(2)面向對象:類與類之間的關系,包含三種:Composition(復合)、Delegation(委托)、 Inheritance(繼承)。

11.1 Composition表示has-a

14.png

如上圖所示,queue類中有deque類,稱為queue has-a deque即類的復合。
這也是一種設計模式Adapter,queue類擁有deque類,而且queue所有的函數功能都借用deque類來實現。deque功能非常全,queue根據用戶開放部分的功能,queue是一種adapter。


15.png

這是復合在內存中的表現,queue類有deque類,deque類有Itr類,sizeof的計算如圖所示:


16.png

類之間在復合關系下構造函數與析構函數的順序為:
(1)構造由內而外。container的構造函數首先調用Component的default構造函數,然后才執行自己。
Container::Container(...):Component(  ){ ... };

(2) 析構由外而內。container的析構函數首先執行自己,然后才調用component的析構函數。

Container::~Container(...){ ... ~Component(  ) };

11.2 Delegation(委托) (Composition by reference)

17.png

(1)如圖所示左邊有指向右邊的指針,這種叫委托。它和復合的區別是復合內外部是一起出現,兩者生命周期同步;而委托則是允許外部先創建出來,等需要的時候再把內部寫好,兩者生命周期不同步。
(2) 圖示寫法叫做Handle/Body或者pointer implementation(pimpl)。左邊是對外的接口,右邊是功能的實現,右邊不影響左邊,右邊可以更改甚至指向別的類,具有良好的彈性。

11.3 Inheritance(繼承)表示is-a

18.png

子類從父類繼承了數據和函數(函數繼承的是調用權)。


19.png

類之間在繼承關系下構造函數與析構函數的順序為:
(1)構造由內而外。Derived的構造函數首先調用Base的default構造函數,然后才執行自己。

Derived::Derived(...):Base(  ){ ... };

(2) 析構由外而內。Derived的析構函數首先執行自己,然后才調用Base的析構函數。Base class的析構必須是virtual,否則會出現undefined behavior!

Derived::~Derived(...){ ... ~Base(  ) };

十二 虛函數與多態

12.1 虛函數及其應用

繼承最有價值的是和虛函數的搭配使用。成員函數從虛函數的角度出發分為三種:
(1)non-virtual函數:你不希望derived class重新定義(override,重寫)它;
(2)virtual函數:你希望derived class重新定義(override,重寫)它,且你對它已有默認定義;
(3)pure virtual函數:你希望derived class一定要重新定義(override,重寫)它,且你對它沒有默認定義。

虛函數應用實例如下:


20.png

舊文件的開啟與讀取,check file name 、search file 、open file任何人寫的都差不多,可以事先寫,但是因為每個人讀取的文件類型不一樣,所以讀取這個動作不能事先寫。框架如下:


21.png

應用框架CDocument中已經事先寫好check file name 、search file等函數,CMyDoc是CDocument的子類,沒法事先寫的Serialize()設計為虛函數(可能為空函數,也可能為純虛函數),使用流程如圖箭頭所示,創建一個子類的對象,通過子類的對象調用父類的函數,遇到Serialize()時父類函數去找子類的定義,然后再將剩余的動作完成,將Serialize()延緩到子類去定義,這種用法就叫做Template Method(23種設計模式之一,Method是java中的函數)。
這種設計模式適合做框架,MFC大量用到Template Method。

具體代碼實現(仿真):


22.png

12.2 繼承+復合關系下的構造與析構

23.png

在圖示繼承+復合關系下構造函數與析構函數的順序為:
(1)構造由內而外。Derived的構造函數首先調用Base的default構造函數,然后調用Component的構造函數,最后才執行自己。

Derived::Derived(...):Base(  ),Component(){ ... };

(2) 析構由外而內。Derived的析構函數首先執行自己,然后調用Component的析構函數,最后調用Base的析構函數。

Derived::~Derived(...){ ... ~Component(),~Base(  ) };
24.png

在圖示繼承+復合關系下構造函數與析構函數的順序為:
(1)構造由內而外。Derived的構造函數首先調用Component的default構造函數,然后調用Base的構造函數,最后才執行自己。

Derived::Derived(...):Component(),Base(  ){ ... };

(2) 析構由外而內。Derived的析構函數首先執行自己,然后調用Base的析構函數,最后調用Component的的析構函數。

Derived::~Derived(...){ ... ~Base(  ) ,~Component()};

12.3 多態實例

功能最強大的是委托+繼承設計方式。
委托+繼承設計實例1(Observer):


25.png

左邊為放數據的class,右邊為觀察的class,左邊可以有很多的右邊,左邊數據裝有指向右邊指針的容器,右邊可以被繼承,將來創建的子類is a Observer都可以放在容器里面,所以可以產生不同的Observer。
左邊要提供注冊和注銷的功能,如圖attach傳入Observer放到容器里頭。左邊還應該有notify把所有Observer進行遍歷,去通知Observer,內容由Observer寫好,左邊調用。


26.png

如圖所示有多個窗口看同一份文件或者不同角度看同一份數據。實現代碼如下:
27.png

委托+繼承設計實例2(Composite):
28.png

文件系統:Primitive代表文件,Composite是一個容器,容納很多個Primitive和Composite,所以設計一個父類Component,Primitive和Composite都is a Component,Component和Composite是委托的關系。add函數和容器類似,add不能設計為純虛函數,因為Primitive不能定義。

委托+繼承設計實例3(Prototype):
我需要一個樹狀繼承體系,子類未來才被派生,不知道未來子類的名稱。讓派生的子類創建一個自己當成原型Prototype,讓我有辦法去看到子類創建出來的的原型放在什么位置上。


29.png

在LandSatImage類里面放一個靜態的對象LAST,他的類型是LandSatImage(自己),構造函數寫成私有的,通過私有的構造函數調用addPrototype,將自己掛上去,addPrototype是父類寫的,它將得到的指針放到容器里頭去,這樣就可以使破折號下面創建的原型放到上面去,可以被上面看到。子類準備一個函數clone,它new一個自己。破折號以上可以通過原型(這是一個對象)可以調用clone這個函數,做出一個副本,如果沒有原型則不能。
clone不能是靜態函數,因為靜態函數的調用需要class name,這里沒有。
實現代碼如下:


30.png

31.png

32.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容