zoukankan      html  css  js  c++  java
  • 条款28:避免返回handles 指向对象内部成分

    1、什么是handles?函数返回handles有什么危害?

    reference、指针、迭代器系统都是所谓的handles(号码牌,用来获得某个对象)。函数返回一个handle,随之而来的便是“减低对象封装性”的风险。它也可能导致:虽调用const成员函数却造成对象状态被更改的风险。

    2、返回handles 指向对象内部成分 可能带来的问题一:自相矛盾

    class Point{
    public:
           Point(intx,inty);
           voidsetX(intnewVal);
           voidsetY(intnewVal);
    };
    
    struct RectData{
           Pointulhc;
           Pointlrhc;
    };
    
    class Rectangle{
    public:
           Point&upperLeft()const{returnpData->ulhc;}
           Point&lowerRight()const{returnpData->lrhc;}
           ...
    private:
           std::tr1::shared_ptr<RectData>pData;
    };
    

    上述代码便是自相矛盾的一个例子。point 类是一个代表点的类,RectData代表一个矩形的结构,Rectangle类则代表一个矩形,该类能够返回表示矩阵的左上和右下的两个点。由于这两个函数为const的,因此所要表达的意思就是,返回矩阵的两个点,但是不能修改他们。但是又又于返回的是点的reference形式,因此通过reference,实际是可以改变返回的点的数据的。因此,造成了自相矛盾。问题的原因就是,函数返回了handle。

    3、上述矛盾带来的启示

    • 成员变量的封装性最多等于“返回其reference”的函数的访问级别。即使数据本身被声明为private的,但是如果返回他们的reference是public的,那么数据的访问权限就编程public了。
    • 如果const成员函数传出一个reference,后者所指数据又不在自身对象内,那么这个函数的调用者可以修改此数据。(这是 bitwise constness 带来的后果。)

    4、改进版 返回const handles 指向对象内部成分 可能带来的问题:解决了自相矛盾,却可能形成虚吊问题

    (1)上述代码的改进版本:在返回handles 的成员函数前加const。这便解决了自相矛盾问题。

    class Rectangle{
    public:
           const Point&upperLeft()const{returnpData->ulhc;}
           const Point&lowerRight()const{returnpData->lrhc;}
           ...
    private:
           std::tr1::shared_ptr<RectData>pData;
    };
    

    (2)上述代码在其他场景下可能存在的问题:虚吊问题
    所谓虚吊问题,就是指针指向了一个不复存在的对象。最常见的问题来源就是函数返回值。

    例如,某个函数返回GUI对象的外框,是一个矩形形式

    	class GUIObject{};
    	const Rectangle boundingBox(constGUIObject&obj);
    	//现在,客户可能这么使用。
    	GUIObject *pgo;
    	const Point *pUpperLeft=&( boundingBox(*pgo).upperLeft() );
    

    boundingBox 函数传入一个GUI对象,它返回一个GUI的外框,即是一个矩形,然后获取这个去腥的右下方的点,并使用一个指针指向它。而函数的返回值是一个临时的对象,即这个矩形是一个临时的对象,当这个语句执行结束后,矩形对象被销毁,因此其内部的点也被销毁,而此时pUpperLeft指向了一个被销毁的点。就形成了所谓的虚吊。

    4、最终的结论

    无论返回的handle是指针、reference、或者迭代器,也无论他是否为const。只要一个handle被传出去了,都是比较危险的。

    5、本条款的例外情况

    有时候必须返回handle,例如operator[],operator=。然而着只是少数的例外。

  • 相关阅读:
    JavaScript 正则表达式
    git常用命令
    用纯css使内容永远居在页面底部
    Oracle中随机抽取N条记录
    表数据回复到某个时候
    oracle同名存储过程被覆盖后如何恢复(转)
    mybatis+spring+mysql
    定位
    关于js的闭包和复制对象
    idea展示runDashboard的窗口
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764167.html
Copyright © 2011-2022 走看看