C++ 包装类的设计

2024-05-08

我必须使用一个界面非常笨拙的旧类。由于我无法更改它并且依赖它,因此我想构建一个包装器,提供一个干净的界面。假设我有课笨手笨脚的班级。基本上,我有三种方法:

1. 参考会员

    Class Wrapper {
      public:
        Wrapper (ClumsyClass& clumsyClass)
          : m_clumsyClass(clumsyClass)
        { }

        int getSmth() {
          return m_clumsyClass.getSmth();
        }

        private:
          ClumsyClass& m_clumsyClass;
}

2. 指针成员

    Class Wrapper {
      public:
        Wrapper (ClumsyClass* clumsyClass)
          : m_clumsyClass(clumsyClass)
        { }

        int getSmth() {
          return m_clumsyClass->getSmth();
        }

        private:
          ClumsyClass* m_clumsyClass;
}

3、继承

    Class Wrapper : public ClumsyClass {
    ...
}

哪种方法是实现包装器的“最干净”方法?我更喜欢第三个,但是当我已经有一个 ClumsyClass 对象然后创建一个 Wrapper 对象(复制构造函数)时,将需要更多内存(因为在我的情况下需要原始类的实例)。


我会避免使用 3,因为它无法封装ClumsyClass。用户Wrapper可以有意或无意地直接访问“笨拙”的界面ClumsyClass这就是你想要避免的。优先选择组合而不是继承。

1. 和 2. 之间的差异很小。使用参考构件会降低包装器的灵活性。该类不可分配,您无法重新设置引用并将其替换为不同的实例ClumsyClass并且该成员不能为空。这些可能是好事也可能是坏事,具体取决于您的要求。

但正如评论中提到的,默认选择可能应该是ClumsyClass作为按值成员Wrapper:

class Wrapper {
  public:
    // possible constructors
    //Wrapper(const ClumsyClass& cc) : m_clumsyClass(cc) {} // copy 
    //Wrapper(ClumsyClass&& cc) : m_clumsyClass(std::move(cc)) {}  // move 
    int getSmth() { return m_clumsyClass.getSmth(); }

  private:
    ClumsyClass m_clumsyClass;
};

在您的特定用例中,有多种原因可能导致这种情况不可能或不理想,然后您可以回退到选项 1 或 2。该决定主要取决于所有权。应该Wrapper“拥有”ClumsyClass还是实例ClumsyClass有一个生命之外的生命Wrapper?

使用直接成员的一个潜在缺点是您无法再隐藏以下实现ClumsyClass在前向声明后面,这样你就失去了一些封装ClumsyClass。值得注意的是,解决这个问题的一种方法是提取一个抽象基类“接口”,Wrapper继承自.就像是:

class IWrapper {
  public:
    virtual ~IWrapper() {}
    virtual int getSmth() = 0;
};

这可能会提供额外的好处,例如可测试性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 包装类的设计 的相关文章

随机推荐

  • Eclipse/Maven:运行 JUnit 测试时未编译它们

    我正在使用 Maven 和 Eclipse m2eclipse 插件 开发一个项目 我在 JUnit 测试中遇到问题 有时 当在 Eclipse 中运行它们时 它们不会被编译 而是使用旧的类文件 当我删除类文件时 我得到ClassNotFo
  • 如何将结果导出为 PDF 报告?

    我正在使用 SonarQube 5 6 3 如何将 SonarQube 分析详细信息报告创建为 PDF 表单 Excel 报告或 html 格式的报告 似乎没有可用的插件 我无法使用以下配置生成 html 文件 sonar issuesRe
  • 引起原因:com.datastax.driver.core.exceptions.InvalidQueryException:日期长度应为 8 或 0 字节 (13)

    我正在尝试使用 spring data cassandra 插入数据 但是当我的应用程序使用 Spring Boot 版本是 1 5 3 运行时 我遇到了以下错误 我在spring data中添加了一个实现CrudResposity的自定义
  • 如何递归列出远程 FTP 的目录内容

    从远程 UNIX FTP 服务器下载文件后 您想要验证是否已正确下载所有文件 您至少会在 Windows 命令提示符中获得类似于 dir s 命令的信息 FTP 客户端在 Windows 上运行 遗憾的是这是为 Unix Linux 用户编
  • 按下主页按钮时 onPause 不会触发

    我有一个安卓AppCompatActivity未能点火onPause按下主页按钮时发生的事件 根据安卓文档 https developer android com guide components activities activity l
  • 使用特殊字符创建正则表达式

    我正在为 mongodb 创建一个查询 app get content title function req res var regexp new RegExp req params title i db find title regexp
  • 删除匿名监听器

    当尝试采用使用匿名或嵌套类实现侦听器的风格时 以便隐藏除侦听之外的其他用途的通知方法 即我不希望任何人能够调用actionPerformed 例如来自java动作监听器 实现与匿名类 https stackoverflow com ques
  • HTML-Entity 转义以防止 XSS

    我有一些用户输入 在我的代码中 我确保对以下符号进行转义 gt amp lt gt lt gt gt gt OWASP https www owasp org index php XSS 28Cross Site Scripting 29
  • 扑。如何检查自动续订订阅是否仍然有效

    我的应用程序有 1 个月的自动续订订阅 当用户单击 购买订阅 按钮时 我将购买日期保存到共享首选项中 然后 1 个月后 我需要检查该订阅是否仍然有效 那么我该如何实施呢 2020 年 3 月 11 日更新 你好 我可以看到那些正在寻找如何在
  • 从云函数在 Google Cloud Storage 中创建新的 csv 文件

    第一次使用 Google 云存储 下面我有一个云函数 每当 csv 文件上传到时就会触发该函数my folder在我的桶里 我的目标是在同一文件夹中创建一个新的 csv 文件 读取上传的 csv 的内容并将每一行转换为将进入新创建的 csv
  • 在 Alpine 中找不到运行时/cgo

    In an alpine edge我安装的容器通过 RUN apk add no cache musl dev go 我试着跑go get github com golang protobuf protoc gen go then 这会导致
  • 来自完整 HTML 文档的 jQuery 对象

    是否可以将完整的 HTML 文档解析为完整的 jQuery 对象 当我尝试时 例如 var tmp p test p console log tmp I get title p test 即一个数组 将所有头部的子项与所有身体的子项组合起来
  • 将数组传递给 json.stringify

    我试图将数组传递给 json stringify 但返回的值返回为空 JSON stringify json data returns json 这是数据的内容 data from email protected cdn cgi l ema
  • Capistrano 杀死资产:预编译

    我正在尝试部署我的应用程序 但我不断收到 err xxx xxx xx xxx bash line 1 9953 Killed bundle exec rake RAILS ENV production RAILS GROUPS asset
  • AWS lambda只读文件系统错误,使用docker镜像存储ML模型

    我在 lambda 上使用 docker 容器映像来运行我的 ML 模型 我的 lambda 函数有一个 S3 触发器来获取图像 我正在尝试运行 lambda 函数 但收到此错误 有人可以帮帮我吗 PS 现在我知道 tmp 是 lambda
  • 同时支持 CommonJS 和 AMD

    有没有办法创建一个 javascript 微型库 没有依赖项的库 支持以下所有模块格式 异步模块定义 CommonJS 将库的导出公开为全局命名空间对象 无加载程序 是的 我把这个答案归功于ded https github com ded
  • C# - 捕获 RTP 流并发送到语音识别

    我正在努力实现的目标 在 C 中捕获 RTP 流 将该流转发到 System Speech SpeechRecognitionEngine 我正在创建一个基于 Linux 的机器人 它将接受麦克风输入 将其发送给 Windows 机器 Wi
  • PlayFramework:如何转换 JSON 数组的每个元素

    鉴于以下 JSON values one two three 我如何在 Scala Play 中像这样转换它 values elem one elem two elem three 这很容易Play 的 JSON 转换器 https www
  • 启动 Java 时使用 -d32 和 -d64

    我阅读了以下摘录JDK 常见问题解答 http www oracle com technetwork java hotspotfaq 138619 html 64bit layering 如何在 32 位和 64 位操作之间进行选择 默认是
  • C++ 包装类的设计

    我必须使用一个界面非常笨拙的旧类 由于我无法更改它并且依赖它 因此我想构建一个包装器 提供一个干净的界面 假设我有课笨手笨脚的班级 基本上 我有三种方法 1 参考会员 Class Wrapper public Wrapper ClumsyC