【问题标题】:design of class inheritance/compostion类继承/组合的设计
【发布时间】:2012-08-10 19:53:46
【问题描述】:

我确实有两个班级:读者和作家。对于这两个类,我都有一个抽象接口,因为数据源/目标应该是灵活的:

class abstract_reader {
...
};

class concrete_reader : public abstract_reader {
   DATATYPE m_data;
...
};    
class abstract_writer {
...
};

class concrete_writer : public abstract_writer {
   DATATYPE m_data;
...
};

编写器应具有读取和写入两种功能。 具体写入器的读取部分的实现与具体读取器的实现相同。结合这些类的好方法是什么?

【问题讨论】:

  • 我很困惑:你有读者和作家,但作家也是读者(那为什么要有单独的读者?),但实际上两者的实现方式相同?
  • 在大多数情况下我只需要一个阅读器,所以有一个阅读器类是有意义的。只有在特殊情况下才需要写作。 m_data 对用户隐藏,但在两种情况下格式相同。在大多数情况下,作者将依赖于数据源中已经存在的数据。如果我有单独的读取器和写入器,我需要将 m_data(这只是一个实现工具)从读取器传递给写入器。流程如下:我读取数据,将部分数据提供给用户,用户创建新数据,用户将新数据提供给编写器,编写器更新数据源。

标签: c++ inheritance abstract-class


【解决方案1】:

你想要的有点混乱,但是有很多方法:

  • 从两个抽象类派生作者
  • 在 writer 中保持一个指向具体 reader 的指针
  • 在 writer 中保存具体 reader 的实例
  • 从编写器中删除读取功能,并创建一个可以读写的第三个类。

就我个人而言,我会遵循最后一种方式,那么您将拥有一整套只读、只写和两者兼用的类。

【讨论】:

  • 我会说最后一个选项涵盖了不同的主题。它说what 去做,而不是how,由前三个给出。
  • @Bartek,是的,我同意。它也不是对OP问题的真正答案,而是关于如何以另一种方式做到这一点的建议。但是,有一个替代方案总是好的;)
【解决方案2】:

为什么作家想知道如何阅读?或许你应该考虑一下 3rd class,结合阅读和写作功能。

如果您确信没问题,只需从abstract_readerabstract_writer 派生作者即可。只要它们是正确实现的接口(例如,没有字段),一切都应该可以正常工作。

哦,也许加入模板会很好(我注意到了神秘的DATATYPE

【讨论】:

    【解决方案3】:
    class concrete_writer : public abstract_writer, public abstract_reader {
    public:
        void read() { // or whatever the proper override is for abstract_reader
            reader.read();
        }
    private:
        concrete_reader reader;
    };
    

    但是,正如@Bartek 指出的那样,有一个名为“writer”的类也可以读取似乎很奇怪。

    【讨论】:

      【解决方案4】:

      首先,如果它只是一个writer,它应该不知道如何阅读。什么 当你在屏幕上实现一个作家时会发生什么?尽管如此,拥有一个 ReaderWriter,除了ReaderWriter,是一个非常 合理的选择,这会产生同样的问题。

      我这样做的方法是首先将ReaderWriter 定义为 继承自ReaderWriter 的接口:

      class Reader
      {
      private:
          //  Pure virtual functions to the implementation...
      public:
          virtual ~Reader() {}
          //  Interface...
      };
      
      class Writer
      {
      private:
          //  Pure virtual functions to the implementation...
      public:
          virtual ~Writer() {}
          //  Interface...
      };
      
      class ReaderWriter : public virtual Reader, public virtual Writer
      {
          //  Just joins the two; adds nothing new of its own
      };
      

      注意虚拟继承。这通常应该是默认值 你正在扩展接口。一旦你有了这个,你可以(通常) 使用 mixins 来实现:

      class ConcreteReader : public virtual Reader
      {
          //  Overrides for the pure virtual functions, + any data needed.
      public:
          ConcreteReader();   //  Or with parameters, as needed.
      };
      
      class ConcreteWriter : public virtual Writer
      {
          //  Overrides for the pure virtual functions, + any data needed.
      public:
          ConcreteWriter();   //  Or with parameters, as needed.
      };
      
      class ConcreteReaderWriter : public ReaderWriter, public ConcreteReader, public ConcreteReaderWriter
      {
      };
      

      收到Reader*的客户端代码可以读取;客户端代码 收到Writer*可以写;和接收到的客户端代码 ReaderWriter 两者都可以。当然,如果客户有 Reader*,它总是可以尝试将dynamic_cast 发送到Writer*ReaderWriter*,如果dynamic_cast成功,也可以写。

      编辑:我忘了说:这种技术被称为 mixins。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-12
        • 2011-04-06
        • 2019-02-08
        • 2021-05-31
        • 1970-01-01
        相关资源
        最近更新 更多