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

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>
            欧美大香线蕉线伊人久久国产精品| 欧美日韩免费高清一区色橹橹| 欧美一级片在线播放| 女同一区二区| 激情成人在线视频| 午夜日韩激情| 99视频在线精品国自产拍免费观看| 久久一区亚洲| 亚洲国产成人不卡| 免费成人av在线看| 久久婷婷麻豆| 91久久中文| 欧美国产综合| 欧美大胆成人| 亚洲激情国产| 亚洲激情视频网| 欧美一区二区久久久| 国产日韩1区| 久久se精品一区二区| 欧美一区1区三区3区公司| 国产一区二区久久| 久久亚洲精品中文字幕冲田杏梨| 亚洲桃色在线一区| 国产欧美69| 国产农村妇女精品一二区| 欧美成人免费va影院高清| 猫咪成人在线观看| 亚洲精品自在在线观看| 欧美日韩一区二区三区在线看 | 久久国产精品一区二区三区| 欧美激情视频一区二区三区免费| 在线观看日韩专区| 伊人久久大香线蕉av超碰演员| 亚洲一区免费在线观看| 欧美日韩免费在线| 久久99伊人| 久久成人这里只有精品| 亚洲精选大片| 亚洲激情第一区| 亚洲人成7777| 欧美+日本+国产+在线a∨观看| 亚洲一品av免费观看| 国产精品一区二区视频| 99综合在线| 一区二区91| 国产伦精品一区二区三区| 久久久久久久欧美精品| 老司机一区二区三区| 99这里有精品| 亚洲欧美自拍偷拍| 亚洲国产美女| 亚洲色在线视频| 亚洲大胆美女视频| 一本久久综合亚洲鲁鲁五月天| 国产美女精品| 亚洲第一成人在线| 国产精品青草综合久久久久99| 美女国产精品| 国产精品萝li| 亚洲国产成人精品久久| 国产精品www网站| 在线性视频日韩欧美| 在线电影一区| 国产日韩欧美精品在线| 国产日韩欧美在线看| 欧美日韩国产限制| 一区二区亚洲精品| 久久成人这里只有精品| 欧美xxx成人| 亚洲风情亚aⅴ在线发布| 亚洲精品国产无天堂网2021| 亚洲欧美日韩成人| 久久深夜福利免费观看| 国产精品99久久久久久久女警 | 日韩香蕉视频| 免费在线看一区| 亚洲国产成人91精品| 亚洲精品久久久久久下一站| 在线观看成人av电影| 亚洲欧美国产精品桃花| 欧美中文字幕不卡| 9l视频自拍蝌蚪9l视频成人| 伊人成人在线视频| 亚洲午夜久久久久久尤物| 亚洲人在线视频| 久久嫩草精品久久久精品一| 久久国产一区| 国产日韩欧美一区二区三区在线观看 | 日韩一区二区高清| 蜜臀a∨国产成人精品| 玖玖综合伊人| 国模私拍视频一区| 欧美在线免费播放| 久久精品视频一| 国产一区二区精品丝袜| 欧美一区深夜视频| 99精品国产福利在线观看免费| 亚洲国产精品久久久久婷婷884| 国产最新精品精品你懂的| 亚洲欧美国产制服动漫| 欧美一区二区三区免费在线看| 国产精品草草| 亚洲欧美激情视频| 久久精品伊人| 在线免费观看日本欧美| 老司机午夜精品| 亚洲国产综合在线看不卡| 亚洲乱码视频| 欧美视频四区| 亚洲欧美精品在线| 久久久亚洲国产天美传媒修理工| 国产亚洲激情在线| 欧美在线视频观看免费网站| 久久精品夜色噜噜亚洲a∨| 黄色欧美日韩| 欧美成人午夜激情| 一区二区三区**美女毛片| 一本色道久久综合| 亚洲自拍电影| 欧美在线免费观看视频| 久久精品99国产精品酒店日本| 久久蜜桃香蕉精品一区二区三区| 久久国产欧美| 欧美日韩在线亚洲一区蜜芽| 国产精品人成在线观看免费 | 欧美电影打屁股sp| 性欧美暴力猛交69hd| 国产色综合天天综合网| 久久久久久久久岛国免费| 免费看亚洲片| 在线亚洲精品| 国内精品嫩模av私拍在线观看| 久久久久久久久久久久久女国产乱| 欧美成人午夜免费视在线看片| 99精品国产高清一区二区| 国产亚洲电影| 欧美日韩国产在线播放| 欧美一区二区在线免费观看| 亚洲国产精品精华液2区45| 亚洲一区三区电影在线观看| 国产精品久久久久毛片软件| 久久资源av| 亚洲综合电影| 亚洲日韩中文字幕在线播放| 久久国内精品自在自线400部| 亚洲人成在线免费观看| 国产色视频一区| 欧美日韩一区二区三区| 久久综合五月| 西西裸体人体做爰大胆久久久| 91久久国产自产拍夜夜嗨| 久久久久久久一区| 亚洲精品综合| 欧美在线播放一区二区| 亚洲精品在线免费| 欧美二区在线看| 久久国产婷婷国产香蕉| 亚洲夜间福利| 99精品国产在热久久| 亚洲电影第1页| 国产视频一区在线观看| 国产精品v一区二区三区| 噜噜噜躁狠狠躁狠狠精品视频 | 亚洲午夜激情网站| 亚洲精品一区二区网址| 亚洲福利精品| 欧美mv日韩mv国产网站app| 午夜在线观看免费一区| 亚洲图片欧洲图片av| 日韩视频―中文字幕| 最新国产成人在线观看| 亚洲国产高清视频| 狠狠爱成人网| 国内久久精品视频| 国产日韩欧美综合一区| 国产精品日本一区二区| 欧美午夜国产| 欧美亚一区二区| 欧美日韩第一页| 欧美激情中文字幕乱码免费| 欧美高清在线播放| 欧美午夜不卡在线观看免费| 香蕉尹人综合在线观看| 久久久久久久网| 久久精品国产清高在天天线| 欧美大片在线观看一区| 亚洲天堂黄色| 欧美精品黄色| 亚洲国产三级在线| 尤物视频一区二区| 国产精品www网站| 午夜精品久久久久久久99热浪潮| 欧美日韩视频一区二区三区| 欧美日本一区二区高清播放视频| 欧美sm视频| 欧美精品色综合| 欧美日韩在线视频一区二区| 国产精品伦理| 一区二区在线视频观看| 在线观看欧美日韩|