Item15:在资源管理类中提供对原始资源的访问

0.概述

  • APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法。
  • 对原始资源的访问可能经由显式转换或隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。

1.举例

资源管理类是对抗资源泄露的堡垒。但是很多API会需要直接访问原始资源,这就需要绕过资源管理对象。

std::tr1::shared_ptr<Investment> pInv(createInvestment()); //使用智能指针保存工厂函数的调用结果

希望某个函数处理Investment对象:

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

调用:

int days=daysHeld(pInv);

上述代码无法通过编译,因为daysHeld需要Investment*指针,而传递的是tr1::shared_ptr<Investment>对象。

2.将RAII class对象转换为其内含的原始资源

2.1 显示转换

trl::shared_ ptr和auto_ptr都提供一个get成员函数,用来执行显式转换,也就是它会返回智能指针内部的原始指针(的复件):

int days = daysHeld(pInv.get());

2.2 隐式转换

作为智能指针,trl::shared_ ptr和auto_ptr都重载了指针取值操作符operator->和operator*,允许隐式转换至底部原始指针:

class Investment
{
    public:
    bool isTaxFree() const;
    ...
};
Investment* createInvestment();
std::tr1::shared_ptr<Investment> pi1(createInvestment());
bool taxable1 = !(pi1->isTaxFree());
std::auto_ptr<Investment> pi2(createInvestment());
bool taxable2 = !((*pi2).isTaxFree());

3.取得RAII对象内的原始资源

3.1 RAII类提供显式转换函数

用于字体的RAII类:

FontHandle getFont();
void releaseFont(FontHandle fh);
class Font{ //RAII class
    public:
        explicit Font(FontHandle fh):f(fh){} //获得资源
        ~Font(){releaseFont(f);} //释放资源
    private:
        FontHandle f; //原始字体资源
};

如果有大量API处理的是FontHandles,将Font对象转换为FontHandle操作将非常频繁。Font类可以提供一个显式转换函数,类似于get:

FontHandle get() const {return f;}

但这样的话每次使用API时都必须调用get:

void changeFontSize(FontHandle f, int newSize);
changeFontSize(f.get(), newFontSize);//显式转换函数

 3.2 RAII类提供隐式转换函数

operator FontHandle() const{return f;}

调用:

changeFontSize(f, newFontSize);//隐式转换

隐式转换比较轻松自然,但是会增加错误发生机会,客户可能会在需要Font时意外创建FontHandle:

Font f1(getFont());
...
FontHandle f2=f1; //本意是要拷贝Font对象,但反而将f1隐式转换为其底部的FontHandle,然后才拷贝

4.补充说明

  • 一般而言显式转换比较安全,但隐式转换对客户比较方便。使用时需要权衡。
  • RAII中返回原始资源的函数确实与封装发生矛盾,但RAII并不是为了封装某物而存在,而是为了确保资源释放这一行为会发生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值