(Boolan) C++面向?qū)ο蟾呒壘幊蹋ㄈ?/h1>

今天來看一看關(guān)于面向?qū)ο蟮木幊痰囊恍﹥?nèi)容,也就是關(guān)于類和類之間的關(guān)系传惠。類和類之間的關(guān)系其實一種抽象的描述現(xiàn)實世界的方法卦方。

現(xiàn)實生活中的事物不都和之前提到的String或者Complex一樣與其他事務(wù)沒有太多的聯(lián)系盼砍,其實從不同角度看到事物往往會得出不同的結(jié)論浇坐。比如近刘,生物界的劃分經(jīng)常是以界門綱目科屬種這樣的思路來劃分的臀晃,找出其共性案淋,然后再***向上抽象 ***得出一個概述性的大類险绘。比如隆圆,生物學(xué)上渺氧,人被分類為真核總界 動物界 后生動物亞界 后口動物總門 脊索動物門 脊椎動物亞門 羊膜總綱 哺乳綱 真獸亞綱 靈長目 類人猿亞目 狹鼻猴次目 類人猿超科 人科 人亞科 人族 人屬 智人種;貓被分類為真核總界 動物界 后生動物亞界 后口動物總門 脊索動物門 脊椎動物亞門 羊膜總綱 哺乳綱 真獸亞綱 食肉目 貓亞科 貓屬 貓種(引自百度百科)慨默。對比貓和人不難發(fā)現(xiàn)弧腥,在真獸亞綱之前和人類沒有區(qū)別虾攻,但是從目開始霎箍,人屬于靈長目漂坏、而貓咪屬于食肉目顶别,從才分道揚(yáng)鑣驯绎。那這些分類對于解釋這個世界到底有什么幫助嗎条篷?這個幫助是很自然的赴叹,比如每往下細(xì)分一個層次乞巧,就意味著區(qū)分的細(xì)節(jié)越細(xì)绽媒,而越往上則越來越抽象。又比如猎提,真核生物中分四個界:原生生物界、真菌界棺聊、植物界和動物界限佩。就拿最熟悉的植物界和動物界來看祟同,他們的區(qū)別是顯著的耐亏,但卻別的點(diǎn)往往是粗糙的沪斟。

畢竟我對生物學(xué)沒有太深的了解,但是這樣一種分類方法在認(rèn)識和解釋世界的過程中卻是通用的槽奕。我們希望通過計算機(jī)來人和世界結(jié)合粤攒,那么還是需要對這樣的認(rèn)識方法有一些了解夯接。

C++相較于C的發(fā)展盔几,主要是出現(xiàn)了對象的概念逊拍,而對象是由各式各樣的class構(gòu)造而成,那么class和class之間的關(guān)系就變得特別重要世曾。因為人和人之間就像是對象和對象之間的關(guān)系肿轨,他們都是同一種class所構(gòu)造而成的,但是屬性卻不相同(性別椒袍、名 字驼唱、名族、膚色驹暑、身高玫恳、體重、性格优俘,生命周期都不一定相同)京办,雖然存在著這些差異,但每個人都還是屬于人類的 (class 人)帆焕。但是人和貓的卻別不僅僅是對象之間的差別了惭婿,更是物種之間的差別了。但是這兩個class之間也并不是完全沒有相同點(diǎn),比如這兩個物種小的時候都得喝奶等等的相同點(diǎn),把這喝奶的的這個特點(diǎn)向上抽取,那么就得到了一個新的class(哺乳綱)[ 可以是** 抽象類 ** ],人和貓這兩個class和新產(chǎn)生的class之間發(fā)生關(guān)系就行了,因為這足夠表示出這倆的關(guān)系了。最后怒坯,我們會得到一棵像樹一樣龐大的一個體系归敬,通過這個體系限番,我們就能很方便的解釋節(jié)點(diǎn)(class之間的關(guān)系)躯舔。

類的基本思想是** 數(shù)據(jù)抽象(data abstraction)** 和 ** 封裝(encapsulation)。數(shù)據(jù)抽象就是一種依賴于 接口(Interface) 實現(xiàn)(implementation)**。類的接口包括用戶所能執(zhí)行的操作;類的實現(xiàn)則包括類的數(shù)據(jù)成員、負(fù)責(zé)接口實現(xiàn)的函數(shù)體以及定義類所需的各種私有函數(shù)。

通過這樣的抽象缠局,不能方便描述class之間的關(guān)系妙啃,還更好的將其中的數(shù)據(jù)進(jìn)行封裝。再拿人和貓來舉例铭拧,貓身上通常都一身漂亮的皮毛搀菩,但人身上基本沒有(如果說人身上的汗毛其實不一定比貓少,那么這就是種詭辯了)。這樣會有一個巨大的好處,讓貓身上的毛很直接的就屬于貓咪吭练,而不會出現(xiàn)在人類的class中。這就實現(xiàn)了非常好的*** 封裝 ***的效果。

這樣的操作圆到,對于數(shù)據(jù)的封裝有著巨大的好處富稻,但是哪怔,這之間也又帶有了一個巨大的方便篷扩,比如,貓咪身上的毛,是貓咪自己的私有屬性宅楞,這時候饲趋,同樣貓也可以具有一個函數(shù)换棚,這個函數(shù)專門用于操作他的私有成員屬性(貓身上的毛),而人則不需要這樣的函數(shù)(方法)爆侣,原因是因為沒有人類這樣的私有成員屬性无虚。

那么為了描述這樣的關(guān)系离唬,我們主要討論class之間的3中關(guān)系嘱函。

三種關(guān)系

  • Inheritance(繼承)

    • 表示is-a的關(guān)系

      struct _List_node_hase
      {
        _List_node_base * _M_next;
        _List_node_base * _M_prev;
      };
      template <typename _Tp>
      struct _List_node
         : public _List_node_base
      {
        _Tp _M_data;
      };
      
    • UML圖


  • 父類的數(shù)據(jù)在public的繼承關(guān)系下祖灰,能夠被完全繼承

  • 父類函數(shù)的調(diào)用權(quán)也可以被子類進(jìn)程

  • Inheritance關(guān)系下的構(gòu)造和析構(gòu)


    • 構(gòu)造:由內(nèi)而外
      • Derived的構(gòu)造函數(shù)首先調(diào)用Base的default構(gòu)造函數(shù)咖祭,然后才執(zhí)行自己
    • 析構(gòu):由外而內(nèi)
      • Derived的析構(gòu)函數(shù)首先執(zhí)行自己,然后才調(diào)用Base的析構(gòu)函數(shù)
  • 虛函數(shù)

    • non-virtual函數(shù):不希望Derived class重新定義(override)
    • virtual函數(shù):希望Derived class 重新定義,且已有默認(rèn)的定義
    • pure virtual函數(shù):希望Derived class一定要重新定義(override),并且沒有默認(rèn)定義
  • Composition(復(fù)合)

    • has-a的關(guān)系

    • 我把他定義為人和長在身上的器官的關(guān)系

        template<class T, class Sequence = deque<T> >
        class queue {
           ....
           protected :
             Sequence c; //底層容器
           public:
             //以下完全利用c的操作函數(shù)完成
            bool empty() const { return c.empty(); }  //其中的操作均為調(diào)用 Sequence c;中所實現(xiàn)的功能
            size_type size() const { return c.size(); }
             ....
        }  
      
      • 在queue中驾凶,持有一個Sequence c 的對象狭郑,queue和Sequence之間的關(guān)系就是Composition
      • 其中UML圖為


        queue 和 sequence 為Composition的關(guān)系
        • 其中黑色菱形一段表示持有另外一個class的對象
      • Adapter設(shè)計模式主要使用了Composition來實現(xiàn)黄绩。Adapter可以很好的將部分功能封裝和開放
    • Composition所占用內(nèi)存的大小等于他持有的所有的成員所占內(nèi)存的總和


    • Composition關(guān)系下的構(gòu)造和析構(gòu)

      • 構(gòu)造:由內(nèi)而外(類似于打包裹)
        • Container的構(gòu)造函數(shù)首先調(diào)用Component的default構(gòu)造函數(shù),然后才執(zhí)行自己的構(gòu)造函數(shù)
          Container:: Container(...) : Component()//Component()由編譯器完成添加
        • 如果不滿意調(diào)用默認(rèn)構(gòu)造函數(shù)那么需要自己來寫需要的構(gòu)造函數(shù)在初始化列表
      • 析構(gòu):由外而內(nèi)(相當(dāng)于拆包裹)
        • Container的析構(gòu)函數(shù)首先執(zhí)行桑谍,然后才會調(diào)用Component的析構(gòu)函數(shù)
          Container:: ~Container(...){ ... ~Component(); } //~Component()有編譯器添加
      • 只需要將自己的構(gòu)造和析構(gòu)完成即可奠骄,順序會有編譯器自動來完成
    • 從生命周期的角度來看,這兩個對象之間的關(guān)系為“同生共死”

    • 我理解Composition類似于人身上的器官含鳞,這些器官由他自己的功能影锈,比如我們需要吸收能力來維持生命,那么我們只需要調(diào)用我們自己的消化系統(tǒng)的消化功能(消化系統(tǒng).消化(食物)蝉绷;)鸭廷,類似于這樣的過程,我們就完成了吸收營養(yǎng)的過程熔吗,但實際這個過程不是人類這個class完成的辆床。并且一旦人死去,這些器官也會死去(這里可不討論捐獻(xiàn)移植拔荨K显亍!V械)咨堤,并且也是人先死,之后的器官一個一個死去晒他。

  • Delegation(委托)

    • Composition by reference(不持有需要的對象吱型,只持有目標(biāo)對象的指針)

    • 我把這個關(guān)系定義為我們和東西關(guān)系

      class StringRep;
      class String{
        .....
        private:
          StringRep* rep;//持有目標(biāo)對象的指針
      }
      
    • UML圖示為


    • 用指針相連,所以兩個對象的生命周期不同

  • 對于這個關(guān)系陨仅,我把他理解為我們和東西關(guān)系津滞,比如我們和手機(jī),我們需要和遠(yuǎn)處的朋友聊天灼伤,我們可以用手機(jī)來完成(只需要調(diào)用手機(jī)的打電話函數(shù)手機(jī)->打電話(電話號碼);)触徐,就相當(dāng)于我們用我們持有的手機(jī)的指來打了一個電話。那為什么是指針呢狐赡,因為我們并不是真正擁有一部手機(jī)撞鹉,我們擁有的只是他的使用權(quán)和處置權(quán)(說白了就是他們都是我們的身外之物,生不帶來死不帶去,在過去鸟雏,大家都共用一部電話享郊,那時候只有使用權(quán),也就反應(yīng)了指針?biāo)笇ο蟮奶攸c(diǎn)孝鹊,可以多個指針變量同時指向一個內(nèi)存中的對象)炊琉。我們可以換手機(jī)(也就是讓我們持有的指針指向另外一個手機(jī)),我們?nèi)绻麤]有手機(jī)的時候又活,那么這個指針指向的就是一個NULL苔咪;我們想要擁有一個手機(jī)的前提是我們必須買一個(也就是為了持有該對象的前提是必須要手動創(chuàng)建)。同樣柳骄,我們和這個對象的生命周期并沒有綁定的關(guān)系团赏,我們死了,手機(jī)還可以用耐薯,手機(jī)壞了舔清,我們健康的活著。所以Delegation的關(guān)系就是一種生不帶來死不帶去的關(guān)系可柿,不過和我們與東西之間的關(guān)系的區(qū)別在于鸠踪,這個類里面有這個指針才有資格擁有這個東西的使用權(quán),如果沒有啊复斥,那也是求不來的营密。這里面有個很大的好處就是,我們可以不斷的換手機(jī)目锭,而對于你的朋友來說他們知不知道你還沒換沒手機(jī)其實不重要评汰,但對你來說,你可以換一臺更好的手機(jī)痢虹,更漂亮的手機(jī)被去。搜易通過Delegation可以作為一個接口,背后通過他持有的指針進(jìn)行實現(xiàn)所需要的功能奖唯,也就是相當(dāng)于惨缆,朋友只要通過號碼就能聯(lián)系你,實現(xiàn)了聯(lián)系的功能丰捷,但這個功能與你用哪部手機(jī)沒多大關(guān)系坯墨,也就實現(xiàn)了不同功能的切換,這也就相當(dāng)于(Handle/Body)的設(shè)計模式的一種現(xiàn)實生活的表現(xiàn)病往,非常方便的幫你完成了實現(xiàn)類的升級捣染。

  • 淺談幾種設(shè)計模式
    這些類與類之間的關(guān)系,構(gòu)成了大量的設(shè)計模式停巷,由于之后專門有課程討論設(shè)計模式的問題耍攘,在這里簡單使用圖例來表示幾種設(shè)計模式榕栏,來說明三種關(guān)系的使用場景。

    • Template Method(模版方法)
模版方法的UML
  • Observer模式
UML
  • Composite(組合模式)
Composite設(shè)計模式的UML
  • Prototype(原型模式)
Prototype的UML
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末蕾各,一起剝皮案震驚了整個濱河市扒磁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌示损,老刑警劉巖渗磅,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異检访,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仔掸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門脆贵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人起暮,你說我怎么就攤上這事卖氨。” “怎么了负懦?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵筒捺,是天一觀的道長。 經(jīng)常有香客問我纸厉,道長系吭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任颗品,我火速辦了婚禮肯尺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躯枢。我一直安慰自己则吟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布锄蹂。 她就那樣靜靜地躺著氓仲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪得糜。 梳的紋絲不亂的頭發(fā)上敬扛,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機(jī)與錄音掀亩,去河邊找鬼舔哪。 笑死,一個胖子當(dāng)著我的面吹牛槽棍,可吹牛的內(nèi)容都是我干的捉蚤。 我是一名探鬼主播抬驴,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缆巧!你這毒婦竟也來了布持?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤陕悬,失蹤者是張志新(化名)和其女友劉穎题暖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捉超,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胧卤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拼岳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枝誊。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惜纸,靈堂內(nèi)的尸體忽然破棺而出叶撒,到底是詐尸還是另有隱情,我是刑警寧澤耐版,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布祠够,位于F島的核電站,受9級特大地震影響粪牲,放射性物質(zhì)發(fā)生泄漏古瓤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一虑瀑、第九天 我趴在偏房一處隱蔽的房頂上張望湿滓。 院中可真熱鬧,春花似錦舌狗、人聲如沸叽奥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朝氓。三九已至,卻和暖如春主届,著一層夾襖步出監(jiān)牢的瞬間赵哲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工君丁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枫夺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓绘闷,卻偏偏與公主長得像橡庞,于是被迫代替她去往敵國和親较坛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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