• 在资源管理类中提供对原始资源的访问【EC++笔记】


    View Code
    由于 某些时刻你需要获取一个 RAII 对象中的原始资源,所以一些 RAII 类的设计者使用了一个小手段来使系统正常运行,那就是:提供一个隐式转换函数。举例说,以下是一个 C 语言 API 中提供的处理字体的一个 RAII 类:

    FontHandle getFont(); // 来自一个 C 语言 API 省略参数表以简化代码
    void releaseFont(FontHandle fh); // 来自同一个 C 语言 API

    class Font // RAII 类
    {
    public:
    explicit Font(FontHandle fh): f(fh) // 通过传值获取资源 因为这一 C 语言 API 这样做
    {
    }
    ~Font() { releaseFont(f); } // 释放资源
    private:
    FontHandle f; // 原始的字体资源
    };

    假设这里有一个大型的相关的 C 语言 API 仅仅通过 FontHandle 解决字体问题,那么将存在十分频繁的把 Font 对象转换为 FontHandle 的操作。
    Font 类可以提供一个显式转换函数,比如 get

    class Font
    {
    public:
    FontHandle get() const { return f; }
    // 进行显式转换的函数
    public:
    explicit Font(FontHandle fh): f(fh) // 通过传值获取资源 因为这一 C 语言 API 这样做
    {
    }
    ~Font() { releaseFont(f); } // 释放资源
    private:
    FontHandle f; // 原始的字体资源
    };

    遗憾的是,这样做使得客户端程序员在每次 与这一 API 通 信时都要调用一次 get

    void changeFontSize(FontHandle f, int newSize); // 来自一个 C 语言 API
    Font f(getFont());
    int newFontSize;
    changeFontSize(f.get(), newFontSize);

    // 显式转换:从 Font 到 FontHandle



    由于需要显式请求这样的转换,这样做显得得不偿失,一些程序员也许会拒绝使用这个类。然而这又增加了字体资源泄漏的可能性,这与 Font 类的设计初衷是完全相悖的。
    有一个替代方案,让 Font 提供一个将其隐式转换为 Fonthandle 的函数:

    class Font
    {
    public:
    operator FontHandle() const { return f; } // 进行隐式转换的函数 规则是 operator T(T为类型 )
    public:
    explicit Font(FontHandle fh): f(fh) // 通过传值获取资源 因为这一 C 语言 API 这样做
    {
    }
    ~Font() { releaseFont(f); } // 释放资源
    private:
    FontHandle f; // 原始的字体资源

    };

    这使得调用这一 C 语言 API 的工作变得简洁而且自然:

    void changeFontSize(FontHandle f, int newSize); // 来自一个 C 语言 API
    Font f(getFont());
    int newFontSize;
    changeFontSize(f, newFontSize); // 隐式转换:从 Font 到 FontHandle


    隐式转换会带来一定的负面效应:它会增加出错的可能。比如说,一个客户端程序员在一个需要 Font 的地方意外地创建了一个 FontHandle :

    Font f1(getFont());
    ...
    FontHandle f2 = f1; // 啊哦!本想复制一个 Font 对象,
    // 但是却却将 f1 隐式转换为其原始的FontHandle ,然后复制它

    现在程序中有一个 FontHandle 资源正在由 Font 对象 f1 来管理,但是仍然可以通过 f2 直接访问 FontHandle 资源。这是很糟糕的。比如说,当 f1 被销毁时,字体就会被释放, f2 也一样。

    是 为 RAII 类提供显式转换为其原始资源的方法,还是允许隐式转换,上面两个问题的答案取决于 RAII 类设计用于完成的具体任务,及其被使用的具体环境。

    最好的设计方案应该遵循第 18 条 的建议,让接口更容易被正确使用,而不易被误用。
  • 相关阅读:
    mysql 查询表结构
    微信网页分享 jssdk config:invalid signature 签名错误
    小程序ios开发注意点
    自己常用易忘的CSS样式
    好久好久没写,,百度API逆地址解析以及删除指定marker
    关于vue打包是因代码校验报错
    git命令行 整理(一位大神给我的私藏)
    百度地图IP定位,点击地图添加marker
    vue-百度地图-maker文字标签显示隐藏
    vue脚手架搭建项目引用百度地图--出坑
  • 原文地址:https://www.cnblogs.com/guyan/p/2411258.html
Copyright © 2020-2023  润新知