• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            思勤無(wú)邪

            上學(xué)時(shí),因我年齡最小,個(gè)頭也最小,上課時(shí),就像大猩猩堆里的猴一般。如今,這猴偶爾也把最近的一些情況寫在這里。

               :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

            公告

                 吾日常三省吾身,曰思、曰勤、曰無(wú)邪。

            積分與排名

            • 積分 - 183659
            • 排名 - 141

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

             

             

                  C++中封裝的概念是把一個(gè)對(duì)象的外觀接口同實(shí)際工作方式(實(shí)現(xiàn))分離開(kāi)來(lái),但是C++的封裝是不完全的,編譯器必須知道一個(gè)對(duì)象的所有部分的聲明,以便創(chuàng)建和管理它。我們可以想象一種只需聲明一個(gè)對(duì)象的公共接口部分的編程語(yǔ)言,而將私有的實(shí)現(xiàn)部分隱藏起來(lái)。C + +在編譯期間要盡可能多地做靜態(tài)類型檢查。這意味著盡早捕獲錯(cuò)誤,也意味著程序具有更高的效率。然而這對(duì)私有的實(shí)現(xiàn)部分來(lái)說(shuō)帶來(lái)兩個(gè)影響:一是即使程序員不能輕易地訪問(wèn)實(shí)現(xiàn)部分,但他可以看到它;二是造成一些不必要的重復(fù)編譯

                        然而C++并沒(méi)有將這個(gè)原則應(yīng)用到二進(jìn)制層次上,這是因?yàn)?/span>C++的類既是描述了一個(gè)接口同時(shí)也描述了實(shí)現(xiàn)的過(guò)程,示例如下:

             

            class CMyString
            {
            private:
             
            const int m_cch;
              
            char *m_psz;
            public:
              CMyString(
            const char *psz);
              
            ~CMyString();
              
            int Length() const;
              
            int Index(const char *psz) const;
            }

             

             

            CMyStirng對(duì)外過(guò)多的暴露了內(nèi)存布局實(shí)現(xiàn)的細(xì)節(jié),這些信息過(guò)度的依賴于這些成員變量的大小和順序,從而導(dǎo)致了客戶過(guò)度依賴于可執(zhí)行代碼之間的二進(jìn)制耦合關(guān)系,這樣的接口不利于跨語(yǔ)言跨平臺(tái)的軟件開(kāi)發(fā)和移植。

             

            1.1.1      Handle-Body模式

             

                   解決這個(gè)問(wèn)題的技術(shù)有一種叫句柄類( handle classes。有關(guān)實(shí)現(xiàn)的任何東西都消失了,只剩一個(gè)單一的指針“m_pThis”。該指針指向一個(gè)結(jié)構(gòu),該結(jié)構(gòu)的定義與其所有的成員函數(shù)的定義都出現(xiàn)在實(shí)現(xiàn)文件中。這樣,只要接口部分不改變,頭文件就不需變動(dòng)。而實(shí)現(xiàn)部分可以按需要任意更動(dòng),完成后只要對(duì)實(shí)現(xiàn)文件進(jìn)行重新編譯,然后再連接到項(xiàng)目中。

                   下面是這項(xiàng)技術(shù)的簡(jiǎn)單例子。頭文件中只包含公共的接口和一個(gè)簡(jiǎn)單的沒(méi)有完全指定的類指針。

             

            class CMyStringHandle
            {
            private:
              
            class CMyString;
              CMyString 
            *m_pThis;
            public:
              CMyStringHandle (
            const char *psz);
              
            ~ CMyStringHandle ();
              
            int Length() const;
              
            int Index(const char *psz) const;
            }


            CMyStringHandle:: CMyStringHandle(
            const char *psz)
            :m_pThis(
            new CMyString(psz));
            {
            }


            CMyStringHandle::
            ~ CMyStringHandle()
            {
               delete m_pThis;
            }


            int CMyStringHandle::Length()
            {
              
            return m_pThis->Length();
            }


            int CMyStringHandle::Index(const char *psz)
            {
             
            return m_pThis->Index(psz);
            }

             

                這是所有客戶程序員都能看到的。
                        class CMyString

            是一個(gè)沒(méi)有完全指定的類型說(shuō)明或類聲明(一個(gè)類的定義包含類的主體)。它告訴編譯器,CMyString是一個(gè)結(jié)構(gòu)的名字,但沒(méi)有提供有關(guān)該結(jié)構(gòu)的任何東西。這對(duì)產(chǎn)生一個(gè)指向結(jié)構(gòu)的指針來(lái)說(shuō)已經(jīng)足夠了。但我們?cè)谔峁┮粋€(gè)結(jié)構(gòu)的主體部分之前不能創(chuàng)建一個(gè)對(duì)象。在這種技術(shù)里,包含具體實(shí)現(xiàn)的結(jié)構(gòu)主體被隱藏在實(shí)現(xiàn)文件中。

             

                        在設(shè)計(jì)模式中,這就叫做Handle-Body 模式,Handle-Body只含有一個(gè)實(shí)體指針,服務(wù)的數(shù)據(jù)成員永遠(yuǎn)被封閉在服務(wù)系統(tǒng)中。

            Handle-Body的布局結(jié)構(gòu)永遠(yuǎn)不會(huì)隨著實(shí)現(xiàn)類數(shù)據(jù)成員的加入或者刪除或者修改而導(dǎo)致Handle-Body的修改,即Handle-Body協(xié)議不依賴于C++實(shí)現(xiàn)類的任何細(xì)節(jié)。這就有效的對(duì)用戶的編譯器隱藏了這些細(xì)節(jié),用戶在使用對(duì)這項(xiàng)技術(shù)時(shí)候,Handle-Body 接口成了它唯一的入口。

             

            然而Handle-Body模式也有自己的弱點(diǎn):

            1、接口類必須把每一個(gè)方法調(diào)用顯示的傳遞給實(shí)現(xiàn)類,這在一個(gè)只有一個(gè)構(gòu)造和一個(gè)析構(gòu)的類來(lái)說(shuō)顯然不構(gòu)成負(fù)擔(dān),但是如果一個(gè)龐大的類庫(kù),它有上百上千個(gè)方法時(shí)候,光是編寫這些方法傳遞就有可能非常冗長(zhǎng),這也增加了出錯(cuò)的可能性。

            2、對(duì)于關(guān)注于性能的應(yīng)用每一個(gè)方法都得有兩層的函數(shù)調(diào)用,嵌套的開(kāi)銷也不理想

            3、由于句柄的存在,依然存在編譯連接器兼容性問(wèn)題。

             

            1.1.2        抽象接口

                        使用了“接口與實(shí)現(xiàn)的分離”技術(shù)的 Handle-Body 解決了編譯器/鏈接器的大部分問(wèn)題,而C++面向?qū)ο缶幊讨械某橄蠼涌谕瑯邮沁\(yùn)用了“接口與實(shí)現(xiàn)分離”的思想,而采用抽象接口對(duì)于解決這類問(wèn)題是一個(gè)極其完美的解決方案。

            1、抽象接口的語(yǔ)言描述:

                        class IMyString

                        {

                          virtual int Length() const = 0; //這表示是一個(gè)純虛函數(shù),具有純虛函數(shù)的接口

                          virtual int Index(const char *psz) const = 0;

                        }

             

            2、抽象接口的內(nèi)存結(jié)構(gòu):

                    抽象接口采用虛函數(shù)表來(lái)調(diào)用成員方法。 

            3、   抽象接口的實(shí)現(xiàn)代碼:

                          接口:

                        class IMyString

                        {

                          virtual int Length() const = 0; //這表示是一個(gè)純虛函數(shù),具有純虛函數(shù)的接口

                          virtual int Index(const char *psz) const = 0;

                        }

                         實(shí)現(xiàn):

                        class CMyStringpublic IMyString

                        {

                        private:

                         const int m_cch;

                          char *m_psz;

                        public:

                          CMyString(const char *psz);

                          virtual ~CMyString();

                          int Length() const;

                          int Index(const char *psz) const;

                        }

                        從上面采用抽象接口的實(shí)例來(lái)看,抽象接口解決了Handle-Body所遺留下來(lái)的全部缺陷。

            抽象接口的一個(gè)典型應(yīng)用:

                        抽象工廠(AbstractFactroy

             

            1.2       多繼承與菱形缺陷、this跳轉(zhuǎn)等

            多重繼承是C++語(yǔ)言獨(dú)有的繼承方式,其它幾乎所有語(yǔ)言都秉承了單一繼承的思想。這是因?yàn)槎嘀乩^承致命的缺陷導(dǎo)致的:

            1.2.1        菱形缺陷

            當(dāng)繼承基類時(shí),在派生類中就獲得了基類所有的數(shù)據(jù)成員副本。假如類B A1A2兩個(gè)類多重繼承而來(lái),這樣B類就包含A1A2類的數(shù)據(jù)成員副本。

            考慮如果A1A2都從某基類派生,該基類稱為Base,現(xiàn)在繼承關(guān)系將出現(xiàn)菱形繼承關(guān)系。


            我們C++語(yǔ)言來(lái)描述這種繼承關(guān)系:

             

            class Base{ }

            class A1 :public Base { }

            class A2 :public Base { }

            class B :public A1,public A2 { }

             

            那么A1A2都具有Base的副本。這樣B就包含了Base的兩個(gè)副本,副本發(fā)生了重疊,不但增加了存儲(chǔ)空間,同時(shí)也引入了二義性。這就是菱形缺陷,菱形缺陷的兩個(gè)缺陷:

            1、子對(duì)象重疊

            2、向上映射的二義性。

            菱形缺陷的其中一種解決辦法是使用虛擬繼承。

             

            C++世界里最廣泛的使用虛擬繼承解決菱形缺陷的應(yīng)用便是標(biāo)準(zhǔn)C++的輸入/輸出iostream

             

             

             

            1.2.2        多重接口與方法名沖突問(wèn)題(Siamese twins

                   對(duì)繼承而來(lái)的虛函數(shù)改寫很容易,但是如果是在改寫一個(gè)“在兩個(gè)基類都有相同原型”的虛函數(shù)情況就不那么容易了。

                   提出問(wèn)題:

                   假設(shè)汽車最大速度的接口為ICar,潛艇最大速度的接口為 IBoat,有一個(gè)兩棲類的交通工具它可以奔跑在馬路上,也可以航行在大海中,那么它就同時(shí)擁有ICarIBoat兩種交通工具的最大速度特性,我們定義它的接口為ICarBoat

                   class ICar

                   {

                         virtual int GetMaxSpeed()= 0

                   }

                   class IBoat

                   {

                  virtual int GetMaxSpeed()= 0

                   }

               我們先對(duì)ICarBoat的接口做一個(gè)嘗試:

                   class CCarBoat

                   {

                          virtual int GetMaxSpeed();//既完成ICarGetMaxSpeed()接口方法又                                     //完成IBoat的接口方法?顯然不能夠

                   };

            解決問(wèn)題:

                   顯然上面這個(gè)嘗試根本就無(wú)法成功,只用一個(gè)實(shí)現(xiàn)方法,怎么能夠求出這個(gè)ICarBoat交通工具奔跑在馬路上的最高時(shí)速,同時(shí)也能夠求出航行在大海上的最大航行速度呢。

                   上面這一問(wèn)題矛盾就在一一個(gè)方法,卻需要兩個(gè)答案。看來(lái)ICarBoat要返回兩個(gè)答案就必須有兩個(gè)方法了,我們假設(shè)一個(gè)方法是求在陸地上奔跑的速度,名稱為GetCarMaxSpeed();另一個(gè)方法是求在大海上航行的最大速度,名稱為GetBoatMaxSpeed();那這兩個(gè)方法又怎么和GetMaxSpeed()接口方法聯(lián)系起來(lái)呢;

             

                   幸運(yùn)的是,我們找到了解決辦法,而且解決辦法有很多種,下面介紹一下繼承法。

                   class IXCar :public ICar

                   {

                         virtual int GetMaxSpeed()

                          {

                                 GetCarMaxSpeed();

                          }

                          virtual int GetCarMaxSpeed() = 0;

                   }

                   class IXBoat:public IBoat

                   {

                          virtual int GetMaxSpeed()

                          {

                                 GetBoatMaxSpeed();

                          }

                          virtual int GetBoatMaxSpeed() = 0;

                   }

                   classCCarBoat: public IXCar , public IXBoat

                   {

                          virtual int GetCarMaxSpeed()

                          {

                                 … …

                          }

                          virtual int GetBoatMaxSpeed()

                          {

                                 … …

                          }

                   };

                  

             

                       

            1.2.3        this跳轉(zhuǎn)

            this跳轉(zhuǎn)是指的“對(duì)象同一性”問(wèn)題。

                  在單一繼承的世界內(nèi),無(wú)論繼承關(guān)系怎么復(fù)雜,針對(duì)于同一對(duì)象,無(wú)論它的子類或者父類的this指針永遠(yuǎn)相等。即如果 BA繼承,那么 對(duì)于一個(gè)已經(jīng)實(shí)例化B類的對(duì)象 bObject,永遠(yuǎn)有(B*&bObject ==(A*)&bObject 成立。

                  但是在多繼承的世界內(nèi),上面的等式就不能恒成立,對(duì)象的同一性受到了挑戰(zhàn)。

                  特別的是,在多繼承世界內(nèi)如果菱形關(guān)系存在情況下,如果對(duì)于已經(jīng)實(shí)例化B類的對(duì)象bObject; Base*)(A1*&bObject != Base*)(A2*&bObject 成立,當(dāng)這種事情發(fā)生的時(shí)候我們就只能特殊處理了。這種情況在COM應(yīng)用中處處都會(huì)發(fā)生。

             

            1.3       C++多態(tài)的兩種多態(tài)形式和區(qū)別

                 C++有兩種多態(tài)多態(tài)形式:

            1、編譯時(shí)刻多態(tài),編譯時(shí)刻多態(tài)依靠函數(shù)重載或者模板實(shí)現(xiàn)

            2、運(yùn)行時(shí)刻多態(tài)。運(yùn)行時(shí)刻多態(tài)依靠需函數(shù)虛接口實(shí)現(xiàn)

            posted on 2007-07-21 16:18 思勤無(wú)邪 閱讀(2212) 評(píng)論(2)  編輯 收藏 引用 所屬分類: C++

            Feedback

            # re: 聊聊封裝、繼承 2007-08-09 20:55 無(wú)
            這好像是華為的培訓(xùn)資料呀  回復(fù)  更多評(píng)論
              

            # re: 聊聊封裝、繼承 2007-12-12 09:09 虎子
            不錯(cuò),不錯(cuò)  回復(fù)  更多評(píng)論
              

            色欲久久久天天天综合网| 国产精品久久久久久久| 久久精品国产只有精品2020| 国内精品久久久久影院亚洲| 久久人搡人人玩人妻精品首页| 狠狠色噜噜狠狠狠狠狠色综合久久| 欧美午夜精品久久久久免费视| 久久精品人妻中文系列| 一本综合久久国产二区| 精品久久久一二三区| 久久久久久免费视频| 久久久久国产精品嫩草影院| 无码人妻久久一区二区三区蜜桃 | 欧美精品乱码99久久蜜桃| 亚洲午夜无码AV毛片久久| 亚洲人成无码www久久久| 色妞色综合久久夜夜| 亚洲熟妇无码另类久久久| 无码人妻久久一区二区三区免费丨| 久久久久亚洲av成人网人人软件| 久久亚洲精品无码aⅴ大香| 亚洲精品99久久久久中文字幕| 青青草原综合久久大伊人| 久久精品国产亚洲av麻豆色欲| 99国产欧美久久久精品蜜芽| 国产精品久久久天天影视香蕉| 久久综合五月丁香久久激情| 日批日出水久久亚洲精品tv| 亚洲熟妇无码另类久久久| 久久91精品国产91久久小草| 国产高潮久久免费观看| 国内精品久久久久影院亚洲| 久久国产色AV免费观看| 久久国产成人午夜AV影院| 久久久久亚洲AV成人网人人网站 | 精品久久久久久亚洲| 久久久久久极精品久久久 | 久久精品国产亚洲av日韩| 国产三级观看久久| 国产69精品久久久久APP下载 | 99久久精品免费看国产一区二区三区 |