(GeekBand)C++面向?qū)ο蟾呒?jí)編程(上)第三周筆記

組合與繼承

Composition(復(fù)合)

復(fù)合關(guān)系

??????? 一個(gè)類(lèi)包含另一個(gè)類(lèi)(has-a),可以通過(guò)Adapter改造一個(gè)類(lèi),即一個(gè)對(duì)象為另一個(gè)對(duì)象的子對(duì)象(成員)。

?????? ?在構(gòu)造時(shí)由內(nèi)而外,先調(diào)用內(nèi)部類(lèi)的構(gòu)造函數(shù),在構(gòu)造自己;在析構(gòu)時(shí),先析構(gòu)自己再析構(gòu)內(nèi)部類(lèi)。

Delegation(委托)

委托關(guān)系

?????? ?一個(gè)類(lèi)里面有一個(gè)指針指向另一個(gè)類(lèi),當(dāng)前類(lèi)委托另一個(gè)類(lèi)實(shí)現(xiàn)各種操作。可以多個(gè)對(duì)象里面的指針指向同一個(gè)委托對(duì)象。兩個(gè)類(lèi)的生命周期不一致。

? ? ? ? Handle/Body模式:將類(lèi)的接口和類(lèi)的實(shí)現(xiàn)相互分開(kāi),對(duì)實(shí)現(xiàn)類(lèi)的修改不會(huì)影響對(duì)外的使用。其相比繼承而言有更大的靈活度。

Inheritance(繼承)

繼承

??? class class_name2:?access_specifiers?class_name1

??? {

??? }

??????? class1完全包含class2的內(nèi)容,calss1為基類(lèi),class2為派生類(lèi)。其構(gòu)造與析構(gòu)順序和復(fù)合關(guān)系一樣,不同的是對(duì)于編譯器來(lái)說(shuō)class2對(duì)象本身就是一個(gè)class1對(duì)象。class1的引用和指針完全可以綁定到class2對(duì)象上。即

class2 cl2;

class1 &cl1=cl2;

class1 *p=&cl2;

??????? 完全是合法的。但是cl1還是一個(gè)class1的引用,p還是一個(gè)class1的指針,所以需要一個(gè)class2類(lèi)型的指針和引用的地方,不能用p和cl1來(lái)代替。


虛函數(shù)與多態(tài)

??????? 基類(lèi)的析構(gòu)函數(shù)必須為virtual(虛函數(shù))。

??????? non-virtual函數(shù):不能被子類(lèi)重新定義(override);

??????? virtual函數(shù):基類(lèi)已經(jīng)默認(rèn)定義了,但是希望子類(lèi)重新定義;

??????? pure virtual函數(shù):沒(méi)有默認(rèn)定義,子類(lèi)必須重新定義;對(duì)于含有純虛函數(shù)的類(lèi)成為抽象類(lèi),不能產(chǎn)生實(shí)例,只能被派生類(lèi)繼承,且如果派生類(lèi)沒(méi)有重新定義的話(huà),派生類(lèi)也為一個(gè)抽象類(lèi)。


繼承+復(fù)合關(guān)系下的構(gòu)造與析構(gòu)


基類(lèi)包含另一個(gè)類(lèi)然后被繼承

?????? 構(gòu)造時(shí)先構(gòu)造Component,然后構(gòu)造基類(lèi)Base,最后才構(gòu)造Derived。析構(gòu)時(shí)先調(diào)用Derived的析構(gòu)函數(shù),然后析構(gòu)Base最后進(jìn)行Component的析構(gòu)。

派生類(lèi)自己包含另一個(gè)類(lèi)

經(jīng)測(cè)驗(yàn)Base的構(gòu)造函數(shù)會(huì)先于Component的構(gòu)造函數(shù)調(diào)用;析構(gòu)時(shí)Component的析構(gòu)函數(shù)先于Base的析構(gòu)函數(shù)調(diào)用。

委托+繼承(composite)

???

文件系統(tǒng)

??????? 為了讓composite中的容器能夠放入primitive和composite兩種不同的類(lèi),那么可以讓這兩個(gè)類(lèi)有同一個(gè)基類(lèi)(繼承)。然后基類(lèi)的指針(委托)可以指向任何一個(gè)派生類(lèi)。


??????? 基類(lèi)不知道會(huì)派生出哪些派生類(lèi),而有需要知道派生出的類(lèi)的名稱(chēng)。在寫(xiě)出派生類(lèi)之后,派生類(lèi)創(chuàng)建一個(gè)自己這種靜態(tài)對(duì)象(LSAT),然后把自己的靜態(tài)對(duì)象添加到基類(lèi)的addPrototype里面的指針中。然后需要?jiǎng)?chuàng)建某一個(gè)派生類(lèi)對(duì)象時(shí)通過(guò)相應(yīng)的靜態(tài)對(duì)象中的clone函數(shù)復(fù)制一個(gè)當(dāng)前對(duì)象,然后為復(fù)制出的對(duì)象的變量賦值完成一個(gè)對(duì)象的創(chuàng)建。

??????? 參考資料sourcemaking.com/design_patterns/prototype;該網(wǎng)站列出了一些參考示例,使用prototype的目的,與存在的問(wèn)題。

作業(yè)過(guò)程中面臨的問(wèn)題與解決方案

???????? 在本次作業(yè)中有兩套不同的解決方案,一種是按照普通的繼承與復(fù)合關(guān)系完成的;另一種是通過(guò)prototype設(shè)計(jì)模式進(jìn)行作業(yè)(未完成)。

??????? 在普通的繼承關(guān)系中存在以下問(wèn)題:

??????? 1. 作業(yè)中要求通過(guò)一個(gè)傳統(tǒng)數(shù)組保存兩種類(lèi)型的對(duì)象,但是對(duì)于數(shù)組的描述中明確表示了數(shù)組是相同類(lèi)型的數(shù)據(jù)按照一定的數(shù)序排列。

???????? 解決方案是,由于兩中類(lèi)都是同一個(gè)類(lèi)Shape的派生類(lèi),而Shape形指針又完全可以指向Shpae及其派生類(lèi)的對(duì)象,所以可以創(chuàng)建一個(gè)Shape形指針數(shù)組,以達(dá)到題目要求。

??????? 2. 由于數(shù)組中是保存的Shape形指針,當(dāng)指針解引用時(shí)也被編譯器當(dāng)作了一個(gè)Shape形的對(duì)象。在輸出流操作符<<重載時(shí),為了使std::cout滿(mǎn)足操作習(xí)慣不能采用成員函數(shù)形式重載。而在普通函數(shù)重載時(shí)就要為Circle與Rectangle各自進(jìn)行一個(gè)重載,參數(shù)如下:

std::ostream& operator <<(std::ostream &os, Rectangle const &re);

std::ostream& operator <<(std::ostream &os, Circle const &ce);

可以看到區(qū)別它們之間不同的為形參列表,但是我的對(duì)象是由Shape指針保存的,不能有效區(qū)分,導(dǎo)致不能調(diào)用相應(yīng)的流操作符。

??????? 解決方案為:可以采用以下兩種方案,將expression轉(zhuǎn)換為type_id對(duì)象的指針或引用

? dynamic_cast<type-id>(expression)

? static_cast < type-id > ( expression )

在進(jìn)行由派生類(lèi)道基類(lèi)的轉(zhuǎn)化時(shí),它們倆沒(méi)什么區(qū)別。但是當(dāng)由基類(lèi)向派生類(lèi)轉(zhuǎn)化時(shí),dynamic_cast具有類(lèi)型檢查,比如expression確實(shí)指向一個(gè)派生類(lèi)對(duì)象時(shí),沒(méi)問(wèn)題返回一個(gè)派生類(lèi)的指針,當(dāng)expression沒(méi)有指向type-id類(lèi)時(shí)返回一個(gè)空指針,可用于判斷。而static_cast由于沒(méi)有類(lèi)型檢查所以下行轉(zhuǎn)換時(shí)時(shí)不安全的。

??????? 3. 對(duì)于**ptr指針作為函數(shù)形參時(shí)const的使用如下:

? ? ? ? ? const MyStructure *? ? ? *ppMyStruct;

??????? // ptr --> ptr --> const MyStructure

??????? MyStructure *const *ppMyStruct;

??????? // ptr --> const ptr --> MyStructure

??????? MyStructure *? ? ? *const ppMyStruct;

?????? ?// const ptr --> ptr --> MyStructure

??????? 如上,如果ptr所指的指針與指針?biāo)傅闹颠€有ptr本身都不會(huì)在函數(shù)中改變的話(huà),可以采用 const *const *const ptr;這種方式。沒(méi)有找到對(duì)這種用法的相關(guān)建議是否應(yīng)該少用之類(lèi)的,但是這種用法確實(shí)對(duì)于理解有一定的困難。

在使用prototype設(shè)計(jì)模式進(jìn)行作業(yè)

? ? ? ? 1. 這種設(shè)計(jì)模式強(qiáng)調(diào)我們?cè)谶\(yùn)行時(shí)去創(chuàng)建一個(gè)對(duì)象時(shí),不需要完全的重新初始化對(duì)象,并且不需要知道對(duì)象屬于哪一個(gè)派生類(lèi)也能夠創(chuàng)建出相應(yīng)的對(duì)象。但是如果兩個(gè)派生類(lèi)所需的構(gòu)造函數(shù)形參列表不同,就不能通過(guò)*shape=class_name()來(lái)改變一個(gè)對(duì)象里面的值,和上面一樣也要通過(guò)類(lèi)型的強(qiáng)制轉(zhuǎn)換“dynamic_cast(expression)”。而像示例代碼這樣添加一個(gè)draw()純虛函數(shù),用以改變對(duì)象的值,但是純虛函數(shù)在復(fù)寫(xiě)的時(shí)候又要求形參列表要和基類(lèi)一樣,而circle和rectangle所需的參數(shù)數(shù)量肯定是不一樣的,最后只有采用笨辦法dynamic_cast改變值。但是網(wǎng)上說(shuō)用了dynamic_cast就代表類(lèi)設(shè)計(jì)上就有問(wèn)題,一個(gè)完好的類(lèi)的設(shè)計(jì)是不需要用到dynamic_cast的~~~~

? ? ? ? 2. 這種設(shè)計(jì)模式在規(guī)模較小的程序中,代碼復(fù)雜度提升太大,為了實(shí)現(xiàn)這個(gè)模式而添加的代碼都差不多和普通的一個(gè)派生類(lèi)的所有代碼行數(shù)相當(dāng)。反而不如普通的直接繼承更方便,也許是我反應(yīng)慢,照著(sourcemaking.com)里面的示例代碼編寫(xiě)了一個(gè)以這種模式為基礎(chǔ)的作業(yè),感覺(jué)有時(shí)候自己都看不懂了~~~~


總結(jié):本章最難的我認(rèn)為就數(shù)設(shè)計(jì)模式這部分了,特別是prototype這種,看示例代碼好像很簡(jiǎn)單,但是一到自己寫(xiě)這種設(shè)計(jì)模式的代碼的時(shí)候,就完全不知道該寫(xiě)什么了呢。反而不明不白的寫(xiě)了好多完全沒(méi)有用的代碼。




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

推薦閱讀更多精彩內(nèi)容