侧边栏壁纸
博主头像
如此肤浅

但行好事,莫问前程!

  • 累计撰写 52 篇文章
  • 累计创建 6 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

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

如此肤浅
2022-05-18 / 0 评论 / 0 点赞 / 33 阅读 / 1,396 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-27,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

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

使用资源管理类通过避免直接处理原始资源的方式防止资源泄露,但有时需要直接使用资源管理类内部的原始资源。有两个做法可以达成目标:显示转换隐式转换

显示转换

tr1::shared_ptr 和 auto_ptr 都提供了一个 get 成员函数,用来执行显示转换,也就是它会返回智能指针内部的原始指针:

std::tr1::shared_ptr<Investment> pInv(createInvestment());
int days = daysHeld(pInv.get()); // 通过get获取到pInv内的原始指针

几乎所有的智能指针都重载了指针取值操作符:

class Investment {
public:
	bool isTaxFree() const;
    ...
};

pInv->isTaxFree(); // 通过operator->访问资源
(*pInv).isTaxFree(); // 通过operator*访问资源

隐式转换

案例:

FontHandle getFont(); // 这是个C API,此处省略了参数
void releaseFont(FontHandle fh); // 来自同一组C API

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

假设有大量与字体相关的 C API,它们处理的是 FontHandles,那么“将 Font 对象转换为 FontHandle”会是一种很频繁的需求。Font class 可为此提供一个显式转换函数,像 get 那样:

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

但频繁的调用 get 函数让人反感,因此另一个方法是令 Font 提供隐式转换:

class Font {
public:
	...
    operator FontHandle() const 
    { return f; }
    ...
};

此时使用 C API 是就会比较轻松:

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

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

Font f1(getFont());
...
// 此处愿意是要拷贝一个Font对象,
// 却将f1隐式转换为其底部的FontHandle,
// 然后才复制它。
FontHandle f2 = f1; 
0

评论区