C++实现之——尽量避免返回handles指向对象内部成分

定义下面的类和结构:

 1 class Point
 2 {
 3 public:
 4      Point(int x, int y);
 5      ...
 6      void setX(int newVal);
 7      void setY(int newVal);
 8 };
 9 struct RectData
10 {
11      Point ulhc;
12      Point lrhc;
13 };
14 class Rectangle
15 {
16      ...
17 private:
18      std::tr1::shared_ptr<RectData> pData; 
19 };

那么下面的成员变量是否有不合理的地方:

1 class Rectange
2 {
3 public:
4     Point& upperLeft() { return pData->ulhc; }
5     Point& lowerRight() { return pData->lrhc; }
6 ...
7 };

上面不合理的地方在第4和第5行,const成员变量的本意是只返回数据,但不允许修改对象内部的数据,但是上面的代码由于返回了指向对象内部变量的handle,破坏了封装性,因为用户可以通过这个handle来修改Point的属性。为了解决这个问题,可以令这个handle为const,这样就不可修改,即:

1 const Point& upperLeft() { return pData->ulhc; }
2 const Point& lowerRight() { return pData->lrhc; }

即使如此,返回指向对象内部的handle还可能带来其他的问题,比如返回一个空的handle,例如下面的代码:

1 class GUIObject { ... };
2 const Rectangle boundingBox(const GUIObject& obj);
3 
4 GUIObject* pgo;
5 ...
6 const Point* pUpperLeft = &(boundingBox(*pgo).upperLeft));

第6行Point指向boundingBox(*pgo)获得的一个临时对象的一个内部成员,但是由于boundingBox(*pgo)返回对象在语句6执行结束后就会被析构,从而导致其内部成员变量Point对象也会被析构,因而pUpperLeft将指向一个空的对象,即变成空悬、虚吊即dangling的handle。

 当然,并不是所有的成员函数都不该返回handle,例如operator[],它需要返回指向容器内部数据的handle。

综上,在定义类的过程中,应避免返回handle指向对象内部成分,这样可以增加封装性,使得const成员函数执行起来真正具有const的性质,并避免得到虚吊的handle。

 

以上整理自Effective C++中文版第三版case 28.

 

 

 

 

posted on 2013-06-03 16:56  Sophia-呵呵小猪  阅读(481)  评论(0编辑  收藏  举报