覆盖一系列子类的方法

时间:2011-05-14 20:56:14

标签: c++ override

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

          Base
          ^
          |
----------+---------------
^      ^     ^     ^     ^ 
|      |     |     |     |
A1     B1    C1    D1    E1
^      ^     ^     ^     ^ 
|      |     |     |     |
A2     B2    C2    D2    E2
.......
^      ^     ^     ^     ^ 
|      |     |     |     |
An     Bn    Cn    Dn    En

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

Base 类当然是所有消息的基类。 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 { .. }
    

    此解决方案的问题在于它引入了 diamond 问题。

    如果其他版本 m 需要覆盖 Base :: SpecificPartOfFunctionality ,还会出现其他问题。根据解决方案,我们将介绍 BaseM ,它将覆盖 Base :: SpecificPartOfFunctionality 。那么将为 BaseN BaseN An 调用 SpecificPartOfFunctionality 。这完全是一团糟。

  3. 有什么建议吗?

2 个答案:

答案 0 :(得分: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> {};

唯一的缺点是你不能轻易地在当前的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) {}
};

  

请注意,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.
};

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

答案 1 :(得分:1)

在全局范围内定义一个实现该功能的友元函数,让SpecificPartsOfFunctionality除了调用它之外什么也不做。 E.g。

void FunctionalityN(Base* b)
{
    b->DoThings();
    ...
}

class An : public Base
{
    friend void FunctionalityN();
    virtual void SpecificPartOfFunctionality() { FunctionalityN(this); }
    ....
};

严格来说,功能N甚至不必是朋友,但它会让事情变得更容易。这样可以直接扩展到Fn,Gn等,然后用FunctionalityN替换NewFunctionalityN非常简单。