我们通常认为一个对象的“内部构件”就是它的数据成员,但是不能被常规地公开访问的成员函数(也就是说,它是 protected 或 private 的)也是对象内部构件的一部分。同样地,不要返回它们的句柄也很重要。这就意味着你绝不应该有一个成员函数返回一个指向拥有较小的可访问级别的成员函数的指针。如果你这样做了,它的可访问级别就会与那个拥有较大的可访问级别的函数相同,因为客户能够得到指向这个拥有较小的可访问级别的函数的指针,然后就可以通过这个指针调用这个函数。
无论如何,返回指向成员函数的指针的函数是难得一见的,所以让我们把注意力返回到 Rectangle 类和它的 upperLeft 和 lowerRight 成员函数。我们在这些函数中挑出来的问题都只需简单地将 const 用于它们的返回类型就可以排除:
class Rectangle { public: ... const Point& upperLeft() const { return pData->ulhc; } const Point& lowerRight() const { return pData->lrhc; } ... }; | 通过这个修改的设计,客户可以读取定义一个矩形的 Points,但他们不能写它们。这就意味着将 upperLeft 和 upperRight 声明为 const 不再是一句空话,因为他们不再允许调用者改变对象的状态。至于封装的问题,我们总是故意让客户看到做成一个 Rectangle 的 Points,所以这是封装的一个故意的放松之处。更重要的,它是一个有限的放松:只有读访问是被这些函数允许的,写访问依然被禁止。
虽然如此,upperLeft 和 lowerRight 仍然返回一个对象内部构件的句柄,而这有可能造成其它方面的问题。特别是,这会导致空悬句柄:引用了不再存在的对象的构件的句柄。这种消失的对象的最普通的来源就是函数返回值。例如,考虑一个函数,返回在一个矩形窗体中的 GUI 对象的 bounding box:
class GUIObject { ... };
const Rectangle // returns a rectangle by boundingBox(const GUIObject& obj); // value; see Item 3 for why // return type is const | |