C ++中的包装器类的设计 [英] Design of a Wrapper Class in C++

查看:145
本文介绍了C ++中的包装器类的设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have to work with an old class with a very clumsy interface. Since I cannot change it and am reliant to it, I want to build a wrapper, offering a clean interface. Let's say I have a class ClumsyClass. Basically, I have three approaches:

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对象(副本构造函数)时,将需要更多的内存(因为在我的情况下必须是原始类的实例)。

Which approach is the "cleanest" way to implement a wrapper? I prefer the third one, but when I already have a ClumsyClass object and then create a Wrapper object (copy constructor), more memory will be needed (since an instance of the original class is necessary in my case).

推荐答案

我会避免使用3,因为它无法封装 ClumsyClass 包装器的用户可以有意或以其他方式直接访问 ClumsyClass 的笨拙界面避免。优先考虑组成而不是继承。

I would avoid 3 as it fails to encapsulate ClumsyClass. Users of Wrapper can, intentionally or otherwise, directly access the "clumsy" interface of ClumsyClass which is what you are trying to avoid. Prefer composition over inheritance.

1和2之间的差异很小。使用参考构件会使包装纸的柔韧性降低。该类不可分配,您无法重置引用并将其替换为 ClumsyClass 的其他实例,并且成员不能为null。

The differences between 1. and 2. are minor. Using a reference member makes the wrapper less flexible. The class is not assignable, you can't reseat the reference and replace it with a different instance of ClumsyClass and the member can't be null. These could be good or bad things depending on your requirements.

但是正如注释中所述,默认选择应该是 ClumsyClass 作为包装器 的按值成员:

But as mentioned in comments, the default choice should probably be to have ClumsyClass as a by-value member of 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。决策主要取决于所有权。 包装器应该拥有 ClumsyClass 还是 ClumsyClass 的生存期不超过 Wrapper

There are number of reasons why this might not be possible or desirable in your particular use case and then you can fall-back to option 1 or 2. The decision depends mostly on ownership. Should Wrapper "own" the ClumsyClass or does the instance of ClumsyClass have a lifetime outside that of Wrapper?

使用直接成员的一个潜在缺点是您不能-更长地将 ClumsyClass 的实现隐藏在前向声明之后,这样您就失去了 ClumsyClass 的某些封装。值得注意的是,解决此问题的一种方法是提取 Wrapper 继承的抽象基类接口。像这样的东西:

One potential downside of using a direct member is you can no-longer hide the implementation of ClumsyClass behind a forward declaration so you lose some of the encapsulation of ClumsyClass. It is worth noting that one way of solving this is to extract out an abstract base class "interface" that Wrapper inherits from. Something like:

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

这可能会提供可测试性等其他好处。

which might provide additional benefits like testability.

这篇关于C ++中的包装器类的设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆