[Effective C++]条款15 在资源管理类中提供对原始资源的访问

本文初发于 “天目中云的小站”,同步转载于此。

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

我们将资源存入资源管理类, 为的是可以免去资源管理的麻烦, 但同时我们也希望可以正常合理地通过资源管理类来使用资源,就像直接使用资源一样, 为此我们一定需要在资源管理类中提供对原始资源的访问.

我们先来解答一些疑问 :

  • 为什么要对原始资源进行访问(为什么要获取原始资源的指针)?
    有时候需要我们传递原始资源的指针, 因为很多C API都是要求传递原始指针才能运作.
  • 如何进行资源访问呢?
    显式转换 或 隐式转换 .

显示转换 : 资源管理类直接提供一个返回原始资源的get()函数, C++提供的智能指针也提供相应的功能.

书中举了一个有关字体资源管理的例子, 代码如下 :

class Font {                           // 对于FontHandle的资源管理类
public:
  	explicit Font(FontHandle fh) :f(fh) {}                                   
  	~Font() { releaseFont(f); }         
    
    FontHandle get() const { return f; } // 直接显示调用该函数即可获得该资源

private:
  	FontHandle f;                        // 原始的字体资源指针
};

假设有一个C API可以通过接受字体资源和字体大小来改变字体 :

// 这是函数
void changeFont(FontHandle f, int newSize);     // C风格的API函数
// 以下是用户具体使用例子
Font f(getFont());
int newFontSize;
...
changeFont(f.get(), newFontSize);	// 使用f.get()

隐式转换 : 提供operator->和operator*的重载直接提供隐式转换函数

前者支持将资源管理类指针隐式转换为底部原始指针, 以此可以直接调用资源函数或取出资源成员变量 :

class Font {                           // 对于FontHandle的资源管理类
public:
  	explicit Font(FontHandle fh) :f(fh) {}                                   
  	~Font() { releaseFont(f); }         
    
    FontHandle get() const { return f; } // 直接显示调用该函数即可获得该资源
    
    // 重载 operator->,返回原始的 FontHandle 指针
    FontHandle* operator->() {
        return &f;  // 返回 FontHandle 的指针,允许访问 FontHandle 的成员
    }

    // 重载 operator*,返回对 FontHandle 的引用
    FontHandle& operator*() {
        return f;  // 返回 FontHandle 的引用,允许访问 FontHandle 的成员
    }

private:
  	FontHandle f;                        // 原始的字体资源指针
};

这样我们就可以完全将资源管理类当做一个指针看待, 通过*取出原始资源, 通过->调用原始资源的成员.

changeFont(*f, newFontSize);  // 假装f是一个指针, 通过解引用调出资源

后者在使用资源管理类时就会默认转换到底部原始指针 :

class Font {                           // 对于FontHandle的资源管理类
public:
  	explicit Font(FontHandle fh) :f(fh) {}                                   
  	~Font() { releaseFont(f); }         
    
    operator FontHandle() const { return f; }        // 隐式转换函数

private:
  	FontHandle f;                        // 原始的字体资源指针
};

这样直接写f就行了 :

changeFont(f, newFontSize);

但是书中并不推荐这样使用, 因为这是一种完全把资源管理类作为原始资源的做法, 也就是说无法再使用有关任何资源管理类自己的操作, 当我们想进行资源管理类的拷贝赋值等操作时, 由于已经隐式转换为了资源, 这样做几乎不会有好下场, 当然你也可以保证完全不使用也不设计这类操作, 让它单独做好资源管理的本职工作, 也是完全可以使用这种方法的.


请记住 :

  • API 往往要求访问原始资源, 所以每个资源管理类都应提供一个取得其原始资源的方法.
  • 对于原始资源的访问, 显示转换一般比较安全, 但隐式转换对客户比较方便, 自己斟酌利弊.

by 天目中云

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值