您的位置:首页 > 其它

条款28:避免返回handles指向对象内部成分

2010-03-10 11:12 495 查看
1、避免返回对象内部构件的句柄(引用,指针,或迭代器)。这样会提高封装性,帮助const成员函数产生const效果。

class Point {// class for representing points
  public:
 Point(int x, int y);
...
void setX(int newVal);
void setY(int newVal);
...
};
struct RectData { // Point data for a Rectangle
  Point ulhc; // ulhc = " upper left-hand corner"
Point lrhc; // lrhc = " lower right-hand corner"
};
class Rectangle {
  ...
  private:
std::tr1::shared_ptr<RectData> pData; // see Item 13 for info on tr1::shared_ptr
};
class Rectangle {
  public:
...
Point& upperLeft() const { return pData->ulhc; }
Point& lowerRight() const { return pData->lrhc; }
...
};
Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2); // rec is a const rectangle from (0, 0) to (100, 100)
//出现问题的代码
rec.upperLeft().setX(50); // now rec goes from (50, 0) to (100, 100)!
//修改后,只有读访问是被这些函数允许的,写访问依然被禁止。
class Rectangle {
public:
...
const Point& upperLeft() const { return pData->ulhc; }
const Point& lowerRight() const { return pData->lrhc; }
...
};


2、将空悬句柄产生的可能性降到最低。可能发生的错误代码:

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对象。到此为止,一切正常,但是我们无法继续了,因为在这个语句的末尾,temp被销毁了,这将间接导致temp的Points的析构。接下来,剩下pUpperLeft指向一个已经不再存在的对象;pUpperLeft 空悬在创建它的语句的末尾!

总结:全部的问题在于一个句柄被返回了,因为一旦这样做了,你就面临着这个句柄比它引用的对象更长寿的风险。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  class struct