青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Shuffy

不斷的學習,不斷的思考,才能不斷的進步.Let's do better together!
posts - 102, comments - 43, trackbacks - 0, articles - 19
【轉】http://m.shnenglu.com/tiandejian/archive/2007/09/23/ec_28.html

第28條:     不要返回指向對象內部部件的“句柄”

假設你正在設計一個與矩形相關的應用程序。每個矩形的區域都由它的左上角和右下角的坐標來表示。為了 Rectangle 對象盡可能的小巧,你可能會做出這樣的決定: Rectangle 自身并不保存這些點的坐標的信息,取而代之的是將這些信息保存在一個輔助結構中,然后讓 Rectangle 指向它:

class Point {                   // 表示點的類

public:

 Point(int x, int y);

 ...

 

 void setX(int newVal);

 void setY(int newVal);

 ...

};

 

struct RectData {               // Rectangle 類使用的點的數據

 Point ulhc;                    // ulhc = " 左上角點的坐標

 Point lrhc;                    // lrhc = " 右下角點的坐標 "

};

 

class Rectangle {

 ...

 

private:

 std::tr1::shared_ptr<RectData> pData;

                                // 關于 tr1::shared_ptr 請參見第 13

};

因為 Rectangle 的客戶端程序員可能需要了解矩形的區域,所以這個類就應該提供 upperLeft lowerRight 函數。然而, Point 卻是一個用戶自定義的類型,因此你可能會回憶起第 20 條的經驗:通過引用傳遞用戶自定義類型的對象要比直接傳值更高效,這些函數可以返回引用來指向更底層的 Point 對象:

class Rectangle {

public:

 ...

 Point& upperLeft() const { return pData->ulhc; }

 Point& lowerRight() const { return pData->lrhc; }

 ...

};

這樣的設計可以通過編譯,但是它卻是錯誤的。實際上,它是自我矛盾的。另外,由于 upperLeft lowerRight 的設計初衷僅僅是為客戶端程序員提供一個途徑來了解 Rectangle 的兩個頂點坐標在哪里,而不是讓客戶端程序員去修改它,因此這兩個函數應聲明為 const 成員函數。另外,這兩個函數都返回指向私有內部數據的引用——通過這些引用,調用者可以任意修改內部數據!請看下邊的示例:

Point coord1(0, 0);

Point coord2(100, 100);

 

const Rectangle rec(coord1, coord2);// rec 是一個 Rectangle 常量

                                    // 兩頂點是 (0, 0), (100, 100)

 

rec.upperLeft().setX(50);            // 但現在 rec 的兩頂點卻變為

                                    // (50, 0), (100, 100)!

upperLeft 返回了 rec 內部的 Point 數據成員,在這里請注意:雖然 rec 本身應該是 const 的,但是調用者竟可以使用 upperLeft 所返回的引用來修改這個數據成員!

上面的現象立刻引出了兩個議題:首先,數據成員僅僅與訪問限制最為寬泛的函數擁有同等的封裝性。在這種情況下,即使 ulhc lrhc 聲明為私有的,它們實際上仍然是公共的,這是因為公共函數 upperLeft lowerRight 返回了指向它們的引用。其次,如果一個 const 成員函數返回一個引用,這一引用指向的數據與一個對象相關,但這一數據卻保存在該對象以外,那么函數的調用者就可以修改這一數據。(這樣恰巧超出了按位恒定的范疇——參見第 3 條。)

我們所做的一切都與返回引用的成員函數有關,但是如果它們返回的是指針或者迭代器,同樣的問題仍然會因為同樣的理由發生。引用、指針、迭代器都可以稱作“句柄”(獲取其它對象的渠道),返回一個指向對象內部部件的句柄,通常都會危及到對象的封裝性。就像我們看到的,即使成員函數是 const 的,返回對象的狀態也是可以任意更改的。

大體上講,對象的“內部部件”主要是它的數據成員,但是非公用的成員函數同樣也是對象的內部部件。與數據成員相同,返回指向成員函數的句柄也是糟糕的設計。這意味著你不應該讓一個公用成員函數 A 返回一個指向非公用成員函數 B 的指針。如果你這樣做了, B 的訪問權層次就與 A 一樣了,這是因為客戶端程序員將能夠取得 B 的指針,然后通過這一指針來調用它。

索性的是,返回指向成員函數指針的函數并不常見,所以讓我們還是把精力放在 Rectangle 類和他的 upperLeft lowerRight 成員函數上來吧。我們所發現的關于這些函數所存在的兩個問題都可以簡單的解決,只要將它們的返回值限定為 const 的就可以了:

class Rectangle {

public:

 ...

 const Point& upperLeft() const { return pData->ulhc; }

 const Point& lowerRight() const { return pData->lrhc; }

 ...

};

使用這一改進的設計方案,客戶端程序員就可以讀取用來定義一個矩形的兩個點,但是他們不可以修改這兩個點。這就意味著將 upperLeft lowerRight 聲明為 const 的并不是一個假象,因為它們將不允許調用者來修改對象的狀態。至于封裝問題,我們一直堅持讓客戶端程序員能能夠看到構造一個 Rectangle 的兩個 Point ,所以說這里我們故意放松了封裝的限制。更重要的是,這一放松是有限的:這些函數僅僅提供了讀的訪問權限。寫權限仍然是禁止的。

class GUIObject { ... };

 

const Rectangle boundingBox(const GUIObject& obj); 

// 以傳值方式返回一個矩形。關于返回值為什么是 const 的,請參見第 3

現在請考慮一下客戶端程序員可能怎樣來使用這個函數:

GUIObject *pgo;                 // pgo 指向某個 GUIObject

 

const Point *pUpperLeft = &(boundingBox(*pgo).upperLeft());

// 取得一個指向 boundingBox 左上角點的指針

調用 boundingBox 將會返回一個新的、臨時的 Retangle 對象。這個對象沒有名字,所以姑且叫它 temp 。隨后 temp 將調用 upperLeft ,然后此次調用將返回一個指向 temp 內部部件的引用,特別地,指向構造 temp 的一個點。 pUpperleft 將會指向這一 Point 對象。到目前為止一切都很完美,但是任務尚未完成,因為在這一語句的最后, boundingBox 的返回值—— temp ——將會被銷毀,這樣間接上會導致 temp Point 被銷毀掉。于是, pUpperLeft 將會指向一個并不存在的對象。這條語句創建了 pUpperLeft ,可也讓它成了孤魂野鬼。

為什么說:任何返回指向對象內部部件句柄的函數都是危險的,這個問題已經一目了然了。至于句柄是指針還是引用還是迭代器,函數是否是 const 的,成員函數返回的句柄本身是不是 const 的,這一切都無關緊要。只有一點,那就是:只要返回了一個句柄,那么就意味著你正在承擔風險:它可能會比它指向的對象存活更長的時間。

這并不意味著你永遠也不能讓一個成員函數返回一個句柄。有些時候你不得不這樣做。比如說, operator[] 允許你獲取 string vector 中的任一元素,這些 operator[] 的工作就是通過返回容器內部的數據來完成的(參見第 3 條)——當容器本身被銷毀時,這些數據同時也會被銷毀。然而,這僅僅是一個例外,不是慣例。

銘記在心

避免返回指向對象內部部件的句柄(引用、指針或迭代器)。這樣做可以增強封裝性,幫助 const 成員函數擁有更加“ const ”的行為,并且使“野句柄”出現的幾率降至最低。

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲一区二区免费看| 欧美一区二区免费观在线| 欧美夜福利tv在线| 99在线精品免费视频九九视| 亚洲人成精品久久久久| 亚洲一级影院| 久久久久国产精品人| 亚洲区国产区| 亚洲一区二区三区免费在线观看| 亚洲二区精品| 欧美视频在线一区二区三区| 亚洲午夜精品网| 夜夜嗨av一区二区三区中文字幕 | 亚洲一级电影| 欧美在线影院在线视频| 狠狠色伊人亚洲综合网站色| 男人天堂欧美日韩| 欧美日韩亚洲视频一区| 欧美一级成年大片在线观看| 亚洲一区二区三区中文字幕| 欧美视频一区二区在线观看 | 久久国产免费| 9久草视频在线视频精品| 欧美一级成年大片在线观看| 国产精品爱久久久久久久| 亚洲欧洲偷拍精品| 欧美一级播放| 欧美国产日韩精品| 午夜激情一区| 亚洲素人一区二区| 夜夜嗨av色综合久久久综合网| 欧美中文字幕精品| 久久久久99| 亚洲一区二区高清| 国产精品www994| 久久久午夜精品| 亚洲黑丝在线| 亚洲你懂的在线视频| 久久精视频免费在线久久完整在线看| 国产日韩欧美三区| 在线视频你懂得一区二区三区| 欧美电影免费观看| 亚洲在线免费| 国产老肥熟一区二区三区| 久久精品一本久久99精品| 国模套图日韩精品一区二区| 亚洲性视频h| 午夜在线电影亚洲一区| 亚洲三级观看| 亚洲美女诱惑| 国产精品久久久久久久久久直播 | 欧美mv日韩mv国产网站| 亚洲黄色影片| 欧美成人第一页| 亚洲欧美精品在线观看| 欧美电影美腿模特1979在线看| 久久成人国产| 久久久久欧美精品| 亚洲欧美激情一区| 亚洲人成网站色ww在线| 亚洲精品小视频| 亚洲视频观看| 亚洲精品久久久久久久久久久| 亚洲午夜精品国产| 亚洲欧美日韩人成在线播放| 久久精品2019中文字幕| 日韩视频精品在线| 亚洲国产小视频在线观看| 欧美资源在线观看| 欧美日韩国产影片| 美女亚洲精品| 久久久水蜜桃| 久热这里只精品99re8久| 午夜一区二区三区不卡视频| 欧美电影免费观看高清| 性欧美超级视频| 欧美日韩视频专区在线播放 | 久久亚洲图片| 在线观看成人一级片| 欧美va亚洲va香蕉在线| 亚洲黄一区二区三区| 精品99一区二区| 亚洲欧洲午夜| 亚洲无线一线二线三线区别av| 亚洲欧美日本日韩| 91久久嫩草影院一区二区| 欧美国产精品劲爆| 久久久久青草大香线综合精品| 亚洲第一区色| 亚洲精品视频二区| 国产农村妇女精品一二区| 欧美在线国产| 欧美xart系列高清| 国产欧美日韩精品专区| 蜜桃av综合| 欧美一区二区三区播放老司机| 国产精品亚洲а∨天堂免在线| a91a精品视频在线观看| 亚洲国产精品久久久久| 欧美日韩一区在线观看视频| 亚洲欧美综合精品久久成人| 国产精品成人v| 欧美成人蜜桃| 精品av久久久久电影| 久久久久久久综合色一本| 国产欧美日韩精品一区| 亚洲黄色成人久久久| 欧美日韩精品在线| 午夜欧美电影在线观看| 午夜亚洲精品| 欧美国产日韩在线观看| 亚洲精品视频免费在线观看| 欧美呦呦网站| 国产麻豆精品在线观看| 久久青青草原一区二区| 国产精品日日摸夜夜添夜夜av| 久久福利影视| 欧美电影免费网站| 久久噜噜噜精品国产亚洲综合 | 精品动漫一区| 欧美黄色网络| 另类天堂视频在线观看| 亚洲欧美视频在线观看| 99在线精品视频| 久久亚洲风情| 亚洲国产精品久久久| 欧美精品亚洲| 亚洲欧美中文日韩在线| 亚洲男人av电影| 亚洲在线视频免费观看| 欧美黑人一区二区三区| 夜夜嗨av一区二区三区网站四季av | 亚洲免费观看高清完整版在线观看熊| 国产精品99久久久久久白浆小说 | 欧美激情乱人伦| 小黄鸭精品密入口导航| 国产精品嫩草久久久久| 欧美大片免费久久精品三p| 欧美成va人片在线观看| 欧美精品九九| 一本到12不卡视频在线dvd| 亚洲高清在线观看| 欧美国产日韩一区二区三区| 国产精品午夜在线| 极品尤物一区二区三区| 国产精品久久福利| 美女视频网站黄色亚洲| 欧美三级不卡| 精品电影在线观看| 激情综合中文娱乐网| 欧美色欧美亚洲高清在线视频| 欧美精品aa| 日韩视频第一页| 欧美国产一区二区三区激情无套| 亚洲精品一区二区三区婷婷月| 亚洲尤物精选| 亚洲蜜桃精久久久久久久| 亚洲欧美综合网| 亚洲精品综合精品自拍| 一片黄亚洲嫩模| 欧美二区在线| 一本久久精品一区二区| 亚洲自拍偷拍福利| 欧美国产日韩一区| 国产精品福利久久久| 国产精品久久久久三级| 亚洲大黄网站| 欧美日韩激情小视频| 国产在线视频不卡二| 欧美大片一区| 国产精品久久久久91| 久久精品三级| 欧美与黑人午夜性猛交久久久| 午夜精品区一区二区三| 久久电影一区| 欧美性大战xxxxx久久久| 夜夜嗨av一区二区三区中文字幕 | 亚洲精品欧洲| 欧美激情亚洲另类| 中文精品99久久国产香蕉| 国产精品成人一区二区艾草| 亚洲影院色无极综合| 亚洲日本欧美日韩高观看| 国产三级精品在线不卡| 亚洲精品孕妇| 国产在线拍揄自揄视频不卡99| 亚洲欧美在线另类| 亚洲男同1069视频| 亚洲国产成人tv| 中文高清一区| 亚洲午夜免费福利视频| 欧美一区在线视频| 99国产成+人+综合+亚洲欧美| 欧美成人亚洲成人| 国产精品羞羞答答| 欧美不卡一卡二卡免费版| 亚洲视频大全| 日韩小视频在线观看| 亚洲综合色丁香婷婷六月图片| 性欧美1819性猛交|