Item 28 不要返回物件內部的控制代碼

2022-05-28 04:39:07 字數 1767 閱讀 1402

控制代碼(handle)可以理解為持有其它物件的方法,引用,指標,和迭代器都是控制代碼。

不要返回物件私有成員的控制代碼。這樣可以增加類的封裝性、使得 const 函式更加 const, 也避免了空引用的建立。

直接返回私有成員的指標會導致私有成員被完全暴露。例如:

class point ;

struct rectdata ;

class rectangle

point& lowerright() const

...private:

std::tr1::shared_ptrpdata; // see item 13 for info on

};

一方面,upperleft 和 lowerright 是被宣告為 const 的成員函式,因為它們被設計成僅僅給客戶提供乙個獲得 rectangle 的點的方法,而不允許客戶改變這個 rectangle。

另一方面,兩個函式都返回引向私有的內部資料的引用——呼叫者可以利用這些引用修改內部資料!例如:

point coord1(0, 0);

point coord2(100, 100);

const rectangle rec(coord1, coord2); // (0, 0) to (100, 100)

rec.upperleft().setx(50); // (50, 0) to (100, 100)

在當前情況下,雖然 ulhc 和 lrhc 被宣告為 private,它們還是被有效地公開了,因為 public 函式 upperleft 和 lowerright 返回了引向它們的引用。

將 const 用於它們的返回型別

class rectangle 

const point& lowerright() const

...};

通過這個修改的設計,客戶可以讀取定義乙個矩形的 points,但他們不能寫它們。

雖然如此,upperleft 和 lowerright 仍然返回乙個物件內部構件的控制代碼,而這有可能造成其它方面的問題。特別是,這會導致空懸控制代碼:引用了不再存在的物件的構件的控制代碼。這種消失的物件的最普通的**就是函式返回值。

考慮乙個函式,返回在乙個矩形窗體中的 gui 物件的 bounding box:

class guiobject ;

const rectangle boundingbox(const guiobject& obj);

考慮客戶可能會這樣使用這個函式:

guiobject *pgo;                           

const point *pupperleft = &(boundingbox(*pgo).upperleft());

對 boundingbox 的呼叫會返回乙個新建的臨時的 rectangle 物件。這個物件沒有名字,所以我們就稱它為 temp。於是 upperleft 就在 temp 上被呼叫,這個呼叫返回乙個引向 temp 的乙個內部構件的引用,特別是,它是由 points 構成的。隨後 pupperleft 指向這個 point 物件。

到此為止,一切正常,但是我們無法繼續了,因為在這個語句的末尾,boundingbox 的返回值—— temp ——被銷毀了,這將間接導致 temp 的 points 的析構。接下來,剩下 pupperleft 指向乙個已經不再存在的物件;pupperleft 空懸在建立它的語句的末尾!

Item 21 需要返回物件時,不要返回引用

乙個典型的場景如下 class rational friend const rational operator const rational lhs,const rational rhs rational a,b rational c a b 注意operator 返回的是 rational 例項,...

避免返回物件內部構件的「控制代碼」

下面的一些想法來自 effective c 中的 item 28 避免返回物件內部構件的 控制代碼 避免返回物件內部構件的控制代碼 引用,指標,或迭代器 也算是指標 如果返回物件內部構建的控制代碼 引用 指標 當物件先於內部控制代碼析構後,內部控制代碼會 空懸 這裡的 空懸 即指標無意義的指向,會引...

Java 不要編寫返回引用可變物件的訪問方法

public class employee 在日常的開發過程中,注意要盡量編寫返回引用可變物件的訪問器的方法。在上邊的employee類中,就違反這種原則,其中的gethirdate 方法返回了乙個date類的物件 在date類中有乙個修改器方法settime,利用這個方法可以設定毫秒數,也就是說d...