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

首先看看下面这个例子:

 class Point{
public:
point(int x, int y);
...
void setX(int newVal);
void setY(int newVal);
...
};
struct RectData{
Point ulhc; //左上角
Point lrhc; //右下角
};
class Rectangle{
...
private:
shared_ptr<RectData> pData;
};

那么如果出现下面这种成员函数的话:

 class Rectangle{
public:
...
Point & upperLeft() const {return pData->ulhc; }
Point & lowerRight() const{return pData->lrhc; }
...
}
这样只是能通过编译,但是设计确是错误的,在成员函数被声明为const的情况下返回了一个内部成员的引用,这样使得ulhc 以及 lrhc对象都可以被更改。但是二者都是private的,实际上二者都是不应该被改变的。
这正是由于返回的是引用,同样的返回指针,迭代其这种叫做handle的对象都是会造成内部状态暴露在外面。
这些问题实际上在每个方法的返回的handle上加上const就会得到解决。
 class Rectangle{
public:
...
const Point & upperLeft() const {return pData->ulhc; }
const Point & lowerRight() const{return pData->lrhc; }
...
}

但是几十这样做仍然可能会导致造成虚调handle的现象发生:

class GUIobject{...};
const Rectangle
boundingBox(const GUIobject & obj);
//那么,当用户这样去使用他的时候
GUIobject * pgo;
...
const Point * pUpperLeft =
&(boundingBox(*pgo).pUpperLeft());
这样实际上将Rectancle中的Point对象传递出去了,这样当临时对象析构的时候,这个指针就会编程一个空悬的指针(感觉通过智能指针就能解决啊),这样也带来了风险。
 
小结:
避免返回Handle指向内部对象,这样可以增加封装性,帮助const函数的行为像是一个const,并将空悬Handle的可能性降到最低。
上一篇:JavaScript高级程序设计学习笔记第九章--客户端检测


下一篇:JavaScript高级程序设计学习笔记第三章--基本概念