删除 C++ 继承中虚拟 class 成员的代码重复

Remove code duplication for virtual class members in C++ inheritance

我现在遇到了一个奇怪的问题。我会写一个真正简化的版本。

class Base
{
public:
  virtual int func1()=0;
  virtual int func2()=0;
protected:
  int n;
};

class der1: public Base
{
  // implements the virtual functions of the base and uses the protected data 
  // members of the base.
};

class der2: public Base
{
  // implements the virtual functions of the base and uses the protected data 
  // members of the base.
}

现在的问题.... der1der2 都以几乎相同的方式实现了 base 的虚函数。但是其他一些 类 (der3, der4) 有自己的实现。但是还是需要继承base。 我如何重构代码以 oop 方式删除代码重复?

选项 1

您可以考虑在 Base class 中使用您最常用的实现。这种方法的主要特点或缺点是基础 class 将不再是抽象的。如果这是一个问题,请转到选项 2。

也许您甚至可以通过使用 template method pattern 来提取由模板方法。

无论如何,对于需要完全不同方法的派生 classes,您只需覆盖 Base class' 方法。

class Base
{
public:
  virtual int func1();
  virtual int func2()=0;
protected:
  virtual void f1_specific_part1()=0;
  virtual void f1_specific_part2()=0; 
  int n;
};
int Base::func1() { // common skeleton of the algorithm
     ...  
     f1_specific_part1(); 
     ... 
     f1_specific_part2(); 
     ...
}     

class Der1: public Base
{ 
protected:
 void f1_specific_part1() override;  // Implements the specific variation
 virtual void f1_specific_part2() override;       
};

选项 2

您可以考虑将派生的 classes 的公共代码分解为 Base class 的受保护方法。

纯虚函数的重写将只调用基础 class 受保护的公共函数(对于 der1der2)或者只使用它们自己完全不同的实现(对于 der3der4)。

class Base
{
public:
  virtual int func1()=0;
  virtual int func2()=0;
protected:
  int common_part1_funct1(); // implements some common parts 
  int common_part2_funct1();
  int n;
};

class Der1: public Base
{
...
  int func1() override { 
     common_part1_funct1();
     ...
     common_part2_funct1(); 
     ... 
  }
};

选项 3 ?

重要说明:我的回答假设大多数派生的 classes 之间有许多共同点。但是,如果您只有一小部分派生的 class 具有一些共同点,那么 Evg 的答案会更合适。

Base12的想法是:

struct Base {
    virtual int func1() = 0;
    virtual int func2() = 0;
};

struct Base12 : Base {
protected:
    int func12();
};

struct Der1: public Base12 {
    virtual int func1() {
        return func12();
    virtual int func2() {
        return func12();
};

struct Der2: public Base12 {
    virtual int func1() {
        return func12();
    virtual int func2() {
        return func12();
};

这是一个使用另一个抽象基础的中间层的解决方案class:

class Base12 : public Base {
protected: 
    int commonFuncStuffA() {
       // Commonly used stuff 
    }

    int commonFuncStuffB() {
    }
};

class der1: public Base12
{
public:
    virtual int func1() {
        n = commonFuncStuffA();
    }
    virtual int func2() {
        n = somethingElse;
    }
};

class der2: public Base12
{
public:
    virtual int func1() {
        n = commonFuncStuffA();
    }
    virtual int func2() {
        n = commonFuncStuffB();
    }
};

虽然我为真正的生产代码设计所做的看起来有点不同。

  1. 为纯虚函数声明一个接口

    struct IMyInterface {
        virtual int func1() = 0;
        virtual int func2() = 0;
        virtual ~IMyInterface {}
    };
    
  2. 提供一个包含常用数据成员和函数的抽象基础class

    class BaseImpl : public IMyInterface {
    protected: 
        int n;
        int commonFuncStuffA() {
            // Commonly used stuff 
        }
    
        int commonFuncStuffB() {
            // Commonly used stuff 
        }
    };
    
  3. 在最终派生的classes

    中提供接口的实现
    class der1: public BaseImpl {
    public:
        virtual int func1() {
            n = commonFuncStuffA();
        }
        virtual int func2() {
            n = somethingElse;
        }
    };
    
    
    class der2: public BaseImpl {
    public:
        virtual int func1() {
            n = commonFuncStuffA();
        }
        virtual int func2() {
            n = commonFuncStuffB();
        }
    };
    
    class der3: public IMyInterface {
    public:
        virtual int func1() {
            // Some completely different implementation of the interface
        }
        virtual int func2() {
            // Some completely different implementation of the interface
        }
    };
    
    class der4: public IMyInterface {
    public:
        virtual int func1() {
            // Some completely different implementation of the interface
        }
        virtual int func2() {
            // Some completely different implementation of the interface
        }
    };