C++之避免返回handles指向对象内部成分(28)---《Effective C++》

来源:互联网 发布:c语言dll库详解 编辑:程序博客网 时间:2024/05/22 17:55

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

在讨论今天这个条款之前,我们先来看看如下代码:

class Point{public:    Point(int x,int y);    ...    void setX(int newVal);    void setY(int newVal);    ...};struct RectDate{    Point rlhc;    Point lrhc;};class Rectangle{public:    ...    Point& upperLeft() const    {        return pData->ulhc;    }    Point& lowerRight() const    {        return Data->lrhc;    };    ...private:    std::trl::shared_ptr<RectData> pData;};

这样的函数编译没有任何问题,但是逻辑上确实不对!我们可以看一下upperLeft和lowerRight函数被声明为const成员函数,因为它们的目的只是为了提供客户一个得知Rectangle相关坐标点的方法,而不是让客户修改Rectangle,但是另外一个方面,返回的是references指向的是Rectangle内部的private数据,但Rectangle内部的private数据却可以调用自身内部的public函数,导致
调用者可以获取这些references进而改变内部数据!导致不安全性出现啦!
那么我们怎样可以解决这个问题呢?
看看书中的解决办法吧!

class Rectangle{public:    ...    const Point& upperLeft()const    {        return pData->ulhc;    }    const Point& lowerRight()const    {        return pData->lrhc;    }    ...};

有了这样的改变,客户就可以取得举行的Points,但不能修改它们吧!

PS:引用(References)、指针和迭代器统统都是所谓的handles(号码牌,用于取得某个对象),而返回一个“代表对象内部数据”的handle,随之而来的是“降低对象封装性”的风险;同时也可以导致像上面所提到的虚假const信息。

有时候,返回handles有可能在其他场合带来问题,更明确的说,可能导致dangling handles(空悬的号码牌),具体见如下代码:

class GUIObject{...};const Rectangle boundingBox(const GUIObject& obj);GUIObject* pgo;...const Point* pUpperLeft=&(boundingBox(*pgo).upper());

对boundingBox的调用获得一个新的、暂时的Rectangle对象,这个对象那个没有名称,我们称之为temp,然后让upperLeft函数作用于temp身上,返回一个指向temp的内部成分的引用,于是pUpperLeft指向那个对象,当upperLeft()函数结束之后,temp将被销毁,于是temp内的Points析构,进而pUpperLeft指向一个不复存在的对象那个,此时pUpperLeft变成悬吊的对象!

总结:避免返回handles(引用,指针、迭代器)指向对象内部,可以保证类的封装性,并将可能发生“dangling handles”的可能性降至最低!

阅读全文
0 0
原创粉丝点击