zoukankan      html  css  js  c++  java
  • effective C++ 条款 15:在资源管理类中提供对原始资源的访问

    资源管理类避免直接处理资源,但是许多APIs直接涉及资源,所以应该提供返回原始资源的函数。

    tr1::shared_ptr和auto_ptr都提供一个get成员函数,用来执行显式转换,返回智能指针内部的原始指针(的复件)。

    std::tr1::shared_ptr<Investment> pInv(createInvestment());

    int daysHeld(const Investment* pi);  //返回投资的天数

    int days = daysHeld(pInv);   //错误;需要的是Investment而传的是std::tr1::shared_ptr<Investment>对象。

    int days = daysHeld(pInv.get()) //将pInv中的原始指针传给daysHeld

    几乎所有智能指针都重载了指针取值操作符(operator->和operator*)允许隐式转换至底部原始指针:

    class Investment {
    public:
        bool isTaxFree()const;
    };
    Investment* createInvestment();
    void f()
    {
        std::tr1::shared_ptr<Investment> pInv1(createInvestment());
        bool taxable = !(pInv1->isTaxFree());//经由operator->访问资源
        ...
        std::tr1::shared_ptr<Investment> pInv2(pInv1);
        bool taxable2 = !((*pInv2).isTaxFree());//经由operator*访问资源
        ...
    }

    FontHandle getFont(); //C API。为简化,暂略参数
    void releaseFont(FontHandle fh);
    class Font
    {
    public:
        explicit Font(FontHandle fh)
            : f(fh)
        {

        }
        FontHandle get()const{return f;} //显式转换函数
        {
            return f;
        }
        ~Font(){releaseFont(f);}
    protected:
    private:
        FontHandle f;
    };
    void changeFontSize(FontHandle f, int newSize);
    Font f(getFont());
    int newFontSize;
    ...
    changeFontSize(f.get(), newFontSize);

    某些程序员认为这样到处处理显式转换,让人倒尽胃口,另一个办法是令Font提供隐式转换函数,转型为FontHandle:

    class Font
    {
    public:
        explicit Font(FontHandle fh)
            : f(fh)
        {

        }
        operator FontHandle() const //隐式转换函数
        {
           return f;
        }
        ~Font(){releaseFont(f);}
    protected:
    private:
        FontHandle f;
    };

    这样客户调用c api时比较轻松自然:

    void changeFontSize(FontHandle f, int newSize);
    Font f(getFont());
    int newFontSize;
    ...
    changeFontSize(f/*.get()*/, newFontSize); //将Font隐式转换为FontHandle

    但是,这个隐式转换会增加错误发生机会,例如客户会在需要Font时意外创建一个FontHandle:

    Font f1(getFont());

    FontHandle f2 = f1; //本意是拷贝一个Font对象管理资源

                                   //却将f1隐式转换成其底部的FontHandle然后复制它。

    以上FontHandle由Font对象f1管理, 但那个FontHandle也可通过直接使用f2取得。那几乎不会有好下场,例如当f1被销毁,字体被释放,而f2因此而成为“虚吊的”(dangle)。

    RAII class内返回原始资源的函数,确实与“封装”发生矛盾,但RAII class 并不是为了封装某物而存在;他们存在是为了确保一个特殊行为--资源释放--会发生。

  • 相关阅读:
    Android——基于监听器的事件处理(转)
    Android——UI事件的处理机制(基于监听器)
    Android——android weight 属性(百度)
    Android——excise(用线性布局、表格布局、相对布局做发送邮件界面)
    Android——gridLayout(网格布局)
    Android——RelativeLayout(相对布局)
    android:layout_gravity和android:gravity的区别
    Android——布局(线性布局linearLayout,表格布局TableLayout,帧布局FrameLayout)
    Android——UI和View——控制方式
    9.0 alpha 版安装出现 could not execute command lessc 的问题
  • 原文地址:https://www.cnblogs.com/lidan/p/2322616.html
Copyright © 2011-2022 走看看