覆盖一系列子类的方法

dim*_*mba 5 c++ overriding

给定遗留代码,系统具有以下类的层次结构:

          Base
          ^
          |
----------+---------------
^      ^     ^     ^     ^ 
|      |     |     |     |
A1     B1    C1    D1    E1
^      ^     ^     ^     ^ 
|      |     |     |     |
A2     B2    C2    D2    E2
.......
^      ^     ^     ^     ^ 
|      |     |     |     |
An     Bn    Cn    Dn    En
Run Code Online (Sandbox Code Playgroud)

层次结构表示某个特定域中的消息.

类当然是所有消息的基类.A1..E1是属于域的版本1,A2..E2到版本2的消息,依此类推.请注意,An必须直接从An-1继承,因为An会覆盖An-1的特定方法.

所有消息都有一些共同的功能,因此它被定义为Base :: PerformFunctionality.功能的某些部分仅特定于版本n,因此存在虚函数Base :: SpecificPartOfFunctionality,它由Base :: PerformFunctionality调用.

所以我的问题是如何通过所有An..En 覆盖Base :: SpecificPartOfFunctionality.

我看到了两种可能的解决方案,我不太喜欢它们:

  1. 在每个An..En中实现Base :: SpecificPartOfFunctionality.

    这个解决方案的问题是每个类的实现应该完全相同,所以我只重复代码.

    另外一个问题是,如果引入了新的类Fn,开发人员可能会忘记实现SpecificPartOfFunctionality.

  2. 引入从Base派生的BaseN类,而每个An..En也派生自BaseN:

    class BaseN : public Base {
       //...
       SpecificPartOfFunctionality() { ...}
    };
    
    class An: public An-1, public BaseN { .. }
    
    Run Code Online (Sandbox Code Playgroud)

    该解决方案的问题在于它引入了钻石问题.

    如果某些其他版本m也需要覆盖Base :: SpecificPartOfFunctionality,则会出现其他问题.根据解决方案,我们将介绍BaseM,它将覆盖Base :: SpecificPartOfFunctionality.因此,这 SpecificPartOfFunctionality将被调用 -的倍欣倍欣.这完全是一团糟.

有什么建议?

Fre*_*urk 3

struct Base {
  virtual void PerformFunctionality() {
    stuff();
    SpecificPartOfFunctionality();
    more_stuff();
  }
private:
  virtual void SpecificPartOfFunctionality() {}
};

template<class Prev>
struct Version3 : Prev {
protected:  // Not private if v4's override might need to call this.
  virtual void SpecificPartOfFunctionality() {
    v3_specific_stuff();
  }
};

struct A1 : Base {};
struct A2 : A1 {};
struct A3 : Version3<A2> {};

struct B1 : Base {};
struct B2 : B1 {};
struct B3 : Version3<B2> {};
Run Code Online (Sandbox Code Playgroud)

唯一的缺点是您无法轻松地在当前 C++ 中转发构造函数,并且为了简单起见,可能始终使用 A2 和 B2 的默认构造函数。

然而,在 C++0x 中,您可以转发构造函数:

template<class Prev>
struct Version3 : Prev {
  using Prev::Prev;
  //...
};

struct C2 : C1 {
  C2(int);  // No default constructor.
};
struct C3 : Version3<C2> {
  C3() : Version3<C2>(42) {}
};
Run Code Online (Sandbox Code Playgroud)

请注意,An 必须直接继承自 An-1,因为 An 会覆盖 An-1 的特定方法。

你误解了一些东西。An 不需要直接继承自 An-1。例如,这工作得很好:

struct Example {
  virtual void f();
};

template<class B>
struct Intermediate : B {};

struct Concrete : Intermediate<Example> {
  virtual void f();  // Overrides Example::f.
};
Run Code Online (Sandbox Code Playgroud)

请记住,如果这不起作用,那么您的 An 首先无法从您的基类覆盖 SpecificPartOfFunctionality!在您的任何示例中, An 都不直接从 Base 继承。