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

            洛譯小筑

            別來(lái)無(wú)恙,我的老友…
            隨筆 - 45, 文章 - 0, 評(píng)論 - 172, 引用 - 0
            數(shù)據(jù)加載中……

            [ECPP讀書(shū)筆記 條目22] 將數(shù)據(jù)成員聲明為私有的

            好吧,以下是我們的計(jì)劃:我們首先要分析為什么數(shù)據(jù)成員不應(yīng)該是公有的,然后繼續(xù)分析為什么數(shù)據(jù)成員也不能是protected的。然后就引出本條款的結(jié)論:數(shù)據(jù)成員必須是私有的。結(jié)論引出,計(jì)劃完成。

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

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

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

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

              int readWrite;              // int值擁有可讀可寫(xiě)級(jí)別訪問(wèn)權(quán)

              int writeOnly;              // int值擁有只寫(xiě)級(jí)別訪問(wèn)權(quán)

            };

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

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

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

            class SpeedDataCollection {

              ...

            public:

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

             

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

             

              ...

            };

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

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

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

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

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

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

            條目23中將介紹這一問(wèn)題:C++中封裝程度與代碼的健壯程度(這段代碼相關(guān)部分被修改時(shí)抵御破壞的能力)成正比。因此,數(shù)據(jù)成員的封裝程度與代碼的健壯程度也是成正比的。比如,當(dāng)一個(gè)數(shù)據(jù)成員從類(lèi)中移除時(shí)(可能你期望使用一次計(jì)算來(lái)代替,就像上文中的averageSoFar一樣),代碼是否會(huì)遭到破壞,將取決于封裝程度。

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

            時(shí)刻牢記

            要將數(shù)據(jù)成員聲明為私有的。這樣可以讓客戶端訪問(wèn)數(shù)據(jù)時(shí)擁有一致的語(yǔ)義,提供有序的訪問(wèn)控制,強(qiáng)制類(lèi)保持一致性,為類(lèi)作者提供更高的靈活性。

            protected并不會(huì)帶來(lái)比public更高的封裝性。

            posted on 2007-06-06 18:37 ★ROY★ 閱讀(1027) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): Effective C++

            91精品国产9l久久久久| 欧美亚洲另类久久综合| 熟妇人妻久久中文字幕| 国产精品VIDEOSSEX久久发布| 无码任你躁久久久久久老妇| 狠狠色丁香久久婷婷综合| 99久久精品免费| 久久夜色精品国产欧美乱| 久久精品亚洲男人的天堂| 日本欧美久久久久免费播放网| 亚洲伊人久久大香线蕉苏妲己| 国产成人精品久久| 久久露脸国产精品| 久久青草国产精品一区| 久久99久久99精品免视看动漫| 国产99久久久国产精免费| 97久久综合精品久久久综合| 亚洲午夜久久久影院| 久久久这里只有精品加勒比| 99久久亚洲综合精品网站| 久久综合精品国产二区无码| 久久婷婷国产剧情内射白浆 | 久久久一本精品99久久精品88| 久久精品国产91久久麻豆自制| 亚洲中文久久精品无码ww16| 色欲综合久久躁天天躁| 久久久久九九精品影院| 嫩草影院久久99| 久久婷婷久久一区二区三区| 亚洲国产另类久久久精品小说| 久久免费视频1| 777午夜精品久久av蜜臀| 中文字幕无码精品亚洲资源网久久| 要久久爱在线免费观看| 久久精品免费全国观看国产| 久久无码高潮喷水| 一本大道久久东京热无码AV| 亚洲中文字幕久久精品无码APP | 91精品国产综合久久香蕉 | 国产精品久久久久蜜芽| 开心久久婷婷综合中文字幕|