條款 38:通過復(fù)合塑模出 has-a 或 “根據(jù)某物實(shí)現(xiàn)出”

Effective C++ 中文版 第三版》讀書筆記

條款 38:通過復(fù)合塑模出 has-a 或 “根據(jù)某物實(shí)現(xiàn)出”

復(fù)合(composition)是類型之間的一種關(guān)系揭厚,當(dāng)某種類型的對象內(nèi)含它種類型的對象没龙,便是這種關(guān)系:

class Address {...}; 

class PhoneNumber {...}; 

class Person { 
public: 
    ... 
private: 
    std::string name; // 合成成分物 
    Address address; // 合成成分物 
    PhoneNumber voiceNumber; // 合成成分物 
    PhoneNumber faxNumber; // 合成成分物 
};

public 繼承帶有 is-a 的意義编丘。復(fù)合也有它自己的意義确虱。實(shí)際上它有兩個意義抢韭。復(fù)合意味 has-a 或 is-implemented-in-terms-of凳谦。那是因?yàn)槟阏蛩阍谀愕能浖刑幚韮蓚€不同的領(lǐng)域念恍。程序中的對象其實(shí)相當(dāng)于你所塑造的世界中的某些事物驹尼,例如人趣避、汽車、等等新翎。這樣的對象屬于應(yīng)用域(application domain)部分程帕。其他對象則純粹是實(shí)現(xiàn)細(xì)節(jié)上的人工制品住练,像是緩沖區(qū)、互斥器愁拭、查找樹等等讲逛。這些對象相當(dāng)于你的軟件的實(shí)現(xiàn)域(implementation domain)。當(dāng)復(fù)合發(fā)生在應(yīng)用域內(nèi)的對象之間岭埠,表現(xiàn)出 has-a 的關(guān)系盏混;當(dāng)復(fù)合發(fā)生在實(shí)現(xiàn)域內(nèi)則是表現(xiàn) is-implemented-in-term-of 的關(guān)系。

上述的 Person class 示范的是 has-a 關(guān)系惜论。

比較麻煩的是區(qū)分 is-a 和 is-implemented-in-term-of 這兩種對象關(guān)系许赃。

假如你想制造出一組 class 用來表現(xiàn)有不重復(fù)對象組成的 sets。而 stl 中 sets 以平衡查找樹(balanced search trees)實(shí)現(xiàn)而成馆类,每個元素耗用 3 個額外指針混聊。而你的程序空間比速度重要。所以你決定復(fù)用 list template 采用 linked lists 來實(shí)現(xiàn)自己的 set乾巧。

你想讓 set 繼承 stl::list:

template<typename T> 
class Set : public std::list<T>{...}; // 將 list 應(yīng)用于 set句喜。錯誤做法。

public 繼承是 is-a 關(guān)系卧抗,但 set 不是一種 list藤滥,因?yàn)閷?list 為真的某些事情對 set 對象并不為真。例如社裆,list 可以內(nèi)含重復(fù)元素,如果 30 被安插到 list<int> 兩次向图,那個 list 將內(nèi)含兩筆 30泳秀,如果 30 被安插到 set<int> 兩次,set 只內(nèi)含一筆 30榄攀。

所以這兩個 classes 之間并非 is-a 關(guān)系嗜傅。不應(yīng)該是 public 繼承,正確的做法是檩赢,set對象可根據(jù)一個 list 對象實(shí)現(xiàn)出來:

template<typename T> 

class Set { 

public: 
    bool member(const T& item) const; 
    void insert(const T& item); 
    void remove(const T& item); 
    std::size_t size() const; 

private: 
    std::list<T> rep; // 用來表述 set 的數(shù)據(jù) 
};

set 的成員函數(shù)可以大量依賴 list 及標(biāo)準(zhǔn)程序庫其他部分來完成吕嘀,所以其實(shí)現(xiàn)很直觀也很簡單,只要你熟悉 stl 編寫程序:

template<typename T> 
bool Set<T>::member(const T& item) const 
{ 
    return std::find(rep.begin(), rep.end(), item) != rep.end(); 
}

template<typename T> 
void Set<T>::insert(const T& item) 
{ 
    if(!member(item)) 
        rep.push_back(item); 
}

template<typename T> 
void Set<T>::remove(const T& item) 
{ 
    typename std::list<T>::iterator it = std::find(rep.begin(), rep.end(), item); 
    if (it != rep.end()) 
        rep.erase(it); 
}

template<typename T> 
std::size_t Set<T>::size() const 
{ 
    return rep.size(); 
}

請記渍曷鳌:

  1. 復(fù)合(composition)的意義和 public 繼承完全不同偶房。
  2. 在應(yīng)用域(application domain),復(fù)合意味著 has-a(有一個)军浆。在實(shí)現(xiàn)域(implementation domain)棕洋,復(fù)合意味 is-implementation-in-terms-of(根據(jù)某物實(shí)現(xiàn)出)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乒融,一起剝皮案震驚了整個濱河市掰盘,隨后出現(xiàn)的幾起案子摄悯,更是在濱河造成了極大的恐慌,老刑警劉巖愧捕,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奢驯,死亡現(xiàn)場離奇詭異,居然都是意外死亡次绘,警方通過查閱死者的電腦和手機(jī)叨橱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來断盛,“玉大人罗洗,你說我怎么就攤上這事「置停” “怎么了伙菜?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長命迈。 經(jīng)常有香客問我贩绕,道長,這世上最難降的妖魔是什么壶愤? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任淑倾,我火速辦了婚禮,結(jié)果婚禮上征椒,老公的妹妹穿的比我還像新娘娇哆。我一直安慰自己,他們只是感情好勃救,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布碍讨。 她就那樣靜靜地躺著,像睡著了一般蒙秒。 火紅的嫁衣襯著肌膚如雪勃黍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天晕讲,我揣著相機(jī)與錄音覆获,去河邊找鬼。 笑死瓢省,一個胖子當(dāng)著我的面吹牛弄息,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播净捅,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼疑枯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛔六?” 一聲冷哼從身側(cè)響起荆永,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤废亭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后具钥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體豆村,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年骂删,在試婚紗的時候發(fā)現(xiàn)自己被綠了掌动。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡宁玫,死狀恐怖粗恢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情欧瘪,我是刑警寧澤眷射,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站佛掖,受9級特大地震影響妖碉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芥被,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一欧宜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拴魄,春花似錦冗茸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至职员,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間跛溉,已是汗流浹背焊切。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芳室,地道東北人专肪。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像堪侯,于是被迫代替她去往敵國和親嚎尤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

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

  • 本原則討論的不是語法和結(jié)構(gòu)上的問題伍宦,而是設(shè)計方面的內(nèi)容芽死。首先你要了解復(fù)合的概念乏梁。所謂復(fù)合就是某種類型的對象中包含了...
    Stroman閱讀 236評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)关贵,斷路器遇骑,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 其實(shí) 談戀愛和叫骰子沒有什么不同 就算你叫到十四個一 明知道你沒有 我還是會加你 因?yàn)?我不想你不開心 的確 愛情...
    語屈源閱讀 281評論 0 0
  • 這一年是大鄴的兆安三十一年,也是故事開始的時候揖曾。 此時落萎,大鄴后宮最風(fēng)光的銅雀臺,一片燈火通明有如白晝炭剪。院子里烏壓壓...
    瑯盡閱讀 324評論 0 0
  • 手上功夫练链,不練就生,一度想棄畫奴拦,硬著頭皮堅(jiān)持下來媒鼓,發(fā)現(xiàn)最終效果沒有預(yù)期的那么差…… 一個業(yè)余繪畫愛好者的堅(jiān)持,加油粱坤!
    YY瑩兒閱讀 326評論 2 5