看下面的问题:
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:
std::tr1::shared_ptr<RectData> pData;
};
现在获取Rectangle的点
class Rectangle{
public:
...
Point& upperLeft() const{return pData->ulhc;}
Point& lowerRight() const{return pData->lrhc;}
...
};
这段代码有什么问题?我们的本意是pData是私有的成员。客端应该是不能够修改其点。但是这里我们可以修改:
Point coord1(0,0);
Point coord2(100,100);
const Rectangle rec(coord1,coord2);
rec.upperLeft().setX(50);//被改变了
为什么这样?因为返回了一个代表对象内部数据的handler,降低了对象的封装性
防止修改,我们可:
class Rectangle{
public:
...
const Point& upperLeft() const{return pData->ulhc;}
const Point& lowerRight() const{return pData->lrhc;}
...
};
但是这不能够改变问题的根本。如:某个函数返回GUI对象的外框
class GUIObject{...};
const Rectangle boundingBox(const GUIObject& obj);
现在,客户可能这样使用:
GUIObject* pgo;
...
const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft());
pUpperLeft会造成悬空指针。因为返回的只是一个临时对象,语句结束临时对象会被销毁。
所以我们说“返回一个handler代表对象内部成分”总是危险的。