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

    请牢记:

    1、APIs往往要求访问原始资源,所以每一个RAII class应该提供一个“取得其所管理之资源”的办法。

    2、对原始资源的访问可能经由显式转换或隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。

    前面条款13的例子中使用了智能指针如auto_ptr或tr1::shared_ptr保存createInvestment的调用结果:

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

    假如某个API希望以某个函数处理Investment对象,返回投资天数,如下:

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

    调用时:

    int days = dayHeld(pInv);  //error!

    因为dayHeld需要的是Investment*指针,而非std::shared_ptr<Investment>的对象!!

    这时就需要一个函数可将RAII类对象转换为所含原始资源(本例为Investment*),有两个方法:显示转换和隐式转换。

    显示转换:

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

    int days = dayHeld(pInv.get());   //将pInv的原始指针传递给dayHeld
    

    隐式转换:

    tr1::shared_ptr和auto_ptr也重载了指针取值操作符(operator->和operator*),允许隐式转换至底部原始指针。

    class Investment{                           //investment继承体系的根类
    public:
        bool isTaxFree() const;
        ...
    };
    Investment* createInvestment();                  //factory函数
    std::tr1::shared_ptr<Investment> pi1(createInvestment());  //令tr1::shared_ptr管理一笔资源
    bool taxable1 = !(pi1->isTaxFree());               //经由operator->访问资源
    ...
    std::auto_ptr<Investment> pi2(createInvestment());      //令auto_ptr管理一笔资源
    bool taxable2 = !((*pi2).isTaxFree());             //经由operator*访问资源
    ...
    

    由于有时候还是必须取得RAII对象内的原始资源,做法是提供一个隐式转换函数,考虑下面的用于字体的RAII类(对CAPI而言字体是一种原生数据结构):

    FontHandle getFont();   //这是一个C API
    

      

    void releaseFont(FontHandle fh);   //同样是C API
    

      

    class Font
    {
    public:
    	explicit Font(FontHandle fh)  //获得资源。 explicit只对构造函数起作用,用来抑制隐式转换。
    		:f(fh)	        //采用值传递 
    	{
    	}
    	~Font()
    	{
    		releaseFont(f);  //释放资源
            } 
    private:
    	FontHandle f;
    };
    

    如果有大量的FontHandles 那么将Font转换成FontHandle比较频繁。Font 类可为此提供一个显示转换函数:

    class Font{
    public:
        ...
        FontHandle get() const {return f;} //显示转换函数
        ...
    };
    

    不幸的是客户每次使用API都必须调用get:

    void changeFontSize(FontHandle f,int newSize); //C API
    Font f(getFont());
    int newFontSize;
    ...
    changeFontSize(f.get(),newFontSize);  //明白地将Font转换为FontHandle
    

    另一个方法是提供隐式转换函数

    class Font{
    public:
        ...
        operator FontHandle() const //隐式转换函数  //转换操作符 定义成 operator T()
        {return f;}
        ...
    };
    

    调用:

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

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

    Font f1(getFont());
    ...
    FontHandle f2 = f1;   //原意是想copy一个Font对象,结果确将f1隐式转换为FontHandle然后copy它。
    

    使用显式还是隐式,取决于具体的使用情况。一般而言显式转换比较安全,但隐式转换对客户比较方便

  • 相关阅读:
    HDU 1102 Constructing Roads
    HDU 1285 确定比赛名次。
    最小生成树 HDU 各种畅通工程的题,prim和kru的模板题
    HDU Jungle Roads 1301 最小生成树、
    并查集小结(转)
    HDU hdu 2094 产生冠军 拓扑排序 判定环
    模运算(转)
    拓扑排序(主要是确定环和加法) HDU 2647 Reward
    HDU 1372 Knight Moves 简单BFS
    用计算机模型浅析人与人之间沟通方式 (一)如何谈话
  • 原文地址:https://www.cnblogs.com/lwenwen/p/3472327.html
Copyright © 2011-2022 走看看