zoukankan      html  css  js  c++  java
  • 在资源管理类中提供对原始资源的访问【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 条 的建议,让接口更容易被正确使用,而不易被误用。
  • 相关阅读:
    数据结构与算法——红黑树
    JAVA数据结构——Map之HashMap
    JAVA数据结构——集合之LinkedList
    在Mac OS X下让你的Terminal带上Color
    Git使用指南(一)
    《乔布斯传》摘录
    必应语音API(Bing text to speech API)
    《设计心理学2》 摘录
    《设计心理学1》 摘录
    第10组 Beta冲刺(4/4)
  • 原文地址:https://www.cnblogs.com/guyan/p/2411258.html
Copyright © 2011-2022 走看看