• <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>

            Shuffy

            不斷的學(xué)習(xí),不斷的思考,才能不斷的進(jìn)步.Let's do better together!
            posts - 102, comments - 43, trackbacks - 0, articles - 19

            【轉(zhuǎn)】http://www.shnenglu.com/tiandejian/archive/2007/06/06/ec_22.html
            第22條:
               
            盡量將數(shù)據(jù)成員聲明為私有的

            好吧,直截了當(dāng)?shù)恼f,在這一條中:我們首先要分析為什么數(shù)據(jù)成員不應(yīng)該是公有的,與此同時(shí),繼續(xù)分析為什么數(shù)據(jù)成員也不能是 protected 的。然后就引出本條款的結(jié)論:數(shù)據(jù)成員必須是私有的。

            那么,數(shù)據(jù)成員為什么不能 public

            讓我們從討論語義的一致性問題開始(另請參見第 18 條)。如果數(shù)據(jù)成員不是公有的,那么客戶端程序員要想訪問對象就只剩下成員函數(shù)一種方法。如果公有接口中所有的東西都是函數(shù),那么客戶端程序員在期望訪問類成員時(shí),由于一切都是函數(shù),所以就可以任意使用,而不用擔(dān)心是否需要使用括號。在整個(gè)過程中,這樣做可以讓你節(jié)省大量躊躇不定的時(shí)間。

            但是也許你會發(fā)現(xiàn),并沒有強(qiáng)制規(guī)定來要求語義的一致性。那么你是否會發(fā)現(xiàn):使用函數(shù)可以讓你更精確地控制數(shù)據(jù)成員的訪問權(quán)?如果把一個(gè)數(shù)據(jù)成員定義為 public 的,那么每個(gè)人對其都擁有“只讀”的訪問權(quán),但是如果你使用函數(shù)來為數(shù)據(jù)成員賦值,或者獲取數(shù)據(jù)成員的值,那么你可以將其實(shí)現(xiàn)為“禁止訪問”、“只讀”以及“可讀可寫”幾種級別的訪問權(quán);嘿,如果需要,你甚至可以將其實(shí)現(xiàn)為“只寫”的訪問權(quán):

            class AccessLevels {

            public:

             ...

             int getReadOnly() const        { return readOnly; }

             void setReadWrite(int value)   { readWrite = value; }

             int getReadWrite() const       { return readWrite; }

             void setWriteOnly(int value)   { writeOnly = value; }

             

            private:

             int noAccess;                  // 禁止訪問此 int

             int readOnly;                  // int 值擁有只讀級別訪問權(quán)

             int readWrite;                 // int 值擁有可讀可寫級別訪問權(quán)

             int writeOnly;                 // int 值擁有只寫級別訪問權(quán)

            };

            很有必要將訪問權(quán)管理得如此有條不紊,因?yàn)樵S多數(shù)據(jù)成員本應(yīng)該被隱藏起來。并不是每個(gè)數(shù)據(jù)成員都需要一個(gè)賦值器和一個(gè)取值器。

            還不是十分肯定?那么現(xiàn)在是時(shí)候使出殺手锏了:“封裝”。如果你通過程序?qū)崿F(xiàn)了對一個(gè)數(shù)據(jù)成員的訪問,那么你就可以使用一次計(jì)算來代替這個(gè)數(shù)據(jù)成員,使用這一個(gè)類的人完全不會有所察覺。

            請看下邊的示例,假設(shè)你正在為一種自動裝置編寫一個(gè)應(yīng)用程序,這一裝置可以監(jiān)視通過汽車的行駛速度,當(dāng)一輛汽車通過時(shí),這一應(yīng)用程序就會計(jì)算出它的速度,然后將這一數(shù)值保存到一個(gè)小型數(shù)據(jù)庫中,其中保存著曾通過所有車輛的速度數(shù)據(jù):

            class SpeedDataCollection {

             ...

            public:

             void addValue(int speed);      // 添加新的數(shù)據(jù)值

             

             double averageSoFar() const;   // 返回速度的平均值

             

             ...

            };

            現(xiàn)在請注意成員函數(shù) averageSoFar 的具體實(shí)現(xiàn)問題。一種實(shí)現(xiàn)方法是:為類添加一個(gè)數(shù)據(jù)成員,讓它保存速度的平均值,隨數(shù)據(jù)庫的改動更新這一成員的數(shù)值。當(dāng)調(diào)用 averageSoFar 時(shí),它僅僅返回這一數(shù)據(jù)成員的值。另一種做法是:在每次調(diào)用 averageSoFar 時(shí)都計(jì)算出這一平均值,此時(shí)需要檢查數(shù)據(jù)庫中所有的數(shù)據(jù)值。

            因?yàn)榈谝环N手段(保存即時(shí)更新的平均值)中,你需要為保存即時(shí)更新平均值、累計(jì)總和以及數(shù)據(jù)的個(gè)數(shù)這幾種數(shù)據(jù)成員分配空間,因此這一方法使得 SpeedDataCollection 對象都變得更大一些。然而, averageSoFar 卻十分的高效。可以把它寫成一個(gè)內(nèi)聯(lián)函數(shù)(參見第 30 條),所做的僅僅是返回這一即時(shí)更新的。相反的是,在需要時(shí)進(jìn)行計(jì)算會使 averageSoFar 變慢,但是 SpeedDataCollection 對象的體積更小。

            二者孰優(yōu)孰劣,誰又能斷定呢?在一個(gè)內(nèi)存較為局促的機(jī)器(比如移動嵌入式設(shè)備)上,并且該應(yīng)用程序不會頻繁的調(diào)用平均值,那么在需要時(shí)計(jì)算的方案就更為優(yōu)秀。相反地,在平均值需要頻繁使用,速度是程序的關(guān)鍵,內(nèi)存不是問題的情況下,則更應(yīng)采用保存一個(gè)即時(shí)平均值的方案。最重要的一點(diǎn)是,在通過成員函數(shù)訪問平均值時(shí)(也就是“封裝”),你可以交替使用這兩種實(shí)現(xiàn)方案(當(dāng)然,你可能還會想到其它重要的問題),客戶端程序員頂多要做的一件事就是重新編譯一下代碼。(即使這一點(diǎn)所帶來的不方便也可以排除。參見第 31 條中介紹的技術(shù)。)

            將數(shù)據(jù)成員隱藏在函數(shù)接口的背后可以使得任意種類的實(shí)現(xiàn)方法更加靈活多變。比如說,這樣做可以非常容易地做到下面幾件事情:提醒其它對象自己的數(shù)據(jù)成員是在被讀還是寫,驗(yàn)證類的恒定性和函數(shù)運(yùn)算的狀態(tài),在多線程系統(tǒng)下進(jìn)行同步操作,等等。如果讓 Delphi C# 的程序員使用 C++ ,他們會發(fā)現(xiàn) C++ 這一特性與這些語言中的“屬性”很相像,只是 C++ 中需要一對括號。

            封裝是 C++ 的一個(gè)博大精深的特性。如果你對客戶端程序員隱藏了數(shù)據(jù)成員的話(也就是將數(shù)據(jù)成員封裝起來),你就可以確保類永遠(yuǎn)保持一致性,這是因?yàn)橹挥谐蓡T函數(shù)可以影響到數(shù)據(jù)成員,你保留了在以后改變具體實(shí)現(xiàn)方法的權(quán)利。如果你不將這些方法隱藏起來,那么你很快就會發(fā)現(xiàn),即使你擁有類的源代碼,你也只能在很小的范圍內(nèi)修改其中公用的部分,因?yàn)檫@樣做會破壞許多客戶端代碼。公用就意味著未封裝,同時(shí)從實(shí)用角度講,未封裝就意味著無法更改,較為廣泛應(yīng)用的類更甚之。然而廣泛應(yīng)用的類最需要使用封裝,因?yàn)樗鼈兛梢詮?#8220;具體實(shí)現(xiàn)可以不斷改良”這一點(diǎn)上獲得最大程度的收益。

            上面的分析對于 protected 數(shù)據(jù)成員也適用。盡管二者乍看上去有一定的區(qū)別,實(shí)際上它們是完全一致的。在使用 public 數(shù)據(jù)成員時(shí),我們分析了語意一致性問題和訪問權(quán)條理性問題,這一分析過程對于使用 protected 數(shù)據(jù)同樣適用。但還有一個(gè)問題——封裝。 protected 數(shù)據(jù)成員不是比 public 的更具有封裝性嗎?從實(shí)用角度講,你會得到一個(gè)令人吃驚的答案:不是。

            23 條中將介紹這一問題: C++ 中封裝程度與代碼的健壯程度(這段代碼相關(guān)部分被修改時(shí),抵御自身遭到破壞的能力)成正比。所以我們可以得出下面的結(jié)論:數(shù)據(jù)成員的封裝程度與代碼的健壯程度也是成正比的。代碼遭到的破壞可能是:將某個(gè)數(shù)據(jù)成員從類中移除。(可能你期望使用一次計(jì)算來代替,就像上文中的 average 一樣。)

            請考慮這個(gè)問題:假設(shè)我們有一個(gè) public 數(shù)據(jù)成員,然后我們把它刪除了,那么將有多少的代碼將遭到破壞呢?我們說,所有使用它的客戶端代碼。這將是一個(gè)。公有數(shù)據(jù)成員就是這樣完全沒有封裝性的。但是繼續(xù)考慮:我們有一個(gè) protected 數(shù)據(jù)成員,然后我們把它刪除了,此時(shí)將破壞多少代碼?我們說,所有使用它的派生類,這同樣是一個(gè)無法預(yù)知巨大數(shù)字。由于在這兩種情況下,如果數(shù)據(jù)成員被更改了,那么將會為客戶端程序員帶來無法估量的損失,因此可以說 protected 數(shù)據(jù)成員與 public 的一樣沒有封裝性。這是違背直覺的,但是有經(jīng)驗(yàn)的類實(shí)現(xiàn)者會告訴你,這是千真萬確的。一旦你聲明了一個(gè) public protected 的數(shù)據(jù)成員,然后客戶端程序員開始使用它,你就很難再對這一數(shù)據(jù)成員做出修改。因?yàn)檫@樣做會帶來太多的代碼重寫、重新測試重新編寫文檔和重新翻譯等等工作。按封裝的理念來說,對于數(shù)據(jù)成員僅僅存在兩個(gè)層次的訪問權(quán),那就是: private (可以提供封裝性)和其它的一切(不提供封裝性)。

            銘記在心

            要將數(shù)據(jù)成員聲明為私有的。這樣可以讓客戶端訪問數(shù)據(jù)時(shí)擁有一致的語義,提供有條不紊的訪問控制,強(qiáng)制類符合一致性,為類作者提供更高的靈活性。

            protected 并不會帶來比 public 更高的封裝性。

            国产精品久久久久影视不卡| 久久国产成人亚洲精品影院| 国产69精品久久久久久人妻精品| 亚洲中文字幕无码久久综合网| 久久精品国产亚洲AV高清热| 国产成人精品久久一区二区三区av| 亚洲国产成人精品女人久久久| 国产成人精品综合久久久| 精品一区二区久久| 久久九九久精品国产免费直播| 久久91精品国产91久久户| 99久久这里只精品国产免费| 久久精品国产亚洲av麻豆小说| 久久人人爽人人爽人人片AV麻豆 | 精品乱码久久久久久久| 久久婷婷综合中文字幕| 蜜臀av性久久久久蜜臀aⅴ| 国产99久久久国产精品~~牛| 亚洲AV无码一区东京热久久| 精品国产91久久久久久久a| 亚洲国产精品久久电影欧美| 色综合久久夜色精品国产| 精品久久777| 精品蜜臀久久久久99网站| 亚洲愉拍99热成人精品热久久| 色婷婷狠狠久久综合五月| 久久久久国色AV免费看图片| 久久ww精品w免费人成| 少妇精品久久久一区二区三区| 精品久久久久久久久免费影院| 久久精品国产亚洲7777| 曰曰摸天天摸人人看久久久| 久久精品视频免费| 久久er国产精品免费观看2| 久久久国产乱子伦精品作者| 久久久久久九九99精品| aaa级精品久久久国产片| 国产精品久久久天天影视| 久久精品成人国产午夜| 91久久九九无码成人网站| 精品久久久久久无码中文字幕|