考虑下面的类:
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::shared_prt<RectData>p;
}
为了计算Rectangle的范围,提供了两个函数:
class Rectangle
{
public:
...
Point& upperLeft()const{return p->ulhc;}
Point& lowerRight()const{return p->lrhc;}
};
这样的设计能通过编译,却是错误的,因为它是自我矛盾的。一方面把upperLeft
和lowerRight
声明成const成员函数,另一方面却返回了引用指向私有内部数据.
可以通过这样调动来修改数据:
const Rectangle rec(coord1,coord2);
rec.upperLeft().setx(50);
如果返回的是指针或迭代器,相同的情况也会发生。
解决这种问题的办法很简单:
class Rectangle
{
public:
...
const Point& upperLeft()const{return p->ulhc;}
const Point& lowerRight()const{return p->lrhc;}
};
这样就无法通过调用这两个函数进行修改了。但是,upperLeft
和lowerRight
还是返回了代表对象内部的handles,有可能在其他场合带来问题:空悬的handles
也就是说handles所指的东西已经不存在了,一旦有个handle被传出去了,你就暴露在"handle"比其所指对象更长寿的风险下.
总结:
避免返回handles(包括引用、指针、迭代器)指向对象内部。遵守这个条款可增加封装线,帮助const成员的函数像个const,兵将发生"悬吊handles"的可能性降至最低.