Search code examples
c++inheritancerefactoringprotectedcode-duplication

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


I have got myself into a strange issue now. Ill write a really simplified version of the same.

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.
}

Now the problem.... both der1 and der2 implements the virtual functions of base pretty much the same way. But some other classes (der3, der4) has their own implementations. But still need to inherit from base. How do i refactor the code to remove the code duplication in an oop manner?


Solution

  • Here's one solution using an intermediate layer of another abstract base 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();
        }
    };
    

    What I'd do for real production code design looks a bit different though.

    1. Declare an interface for the pure virtual functions

      struct IMyInterface {
          virtual int func1() = 0;
          virtual int func2() = 0;
          virtual ~IMyInterface {}
      };
      
    2. Provide a abstract base class with the commonly used data members and functions

      class BaseImpl : public IMyInterface {
      protected: 
          int n;
          int commonFuncStuffA() {
              // Commonly used stuff 
          }
      
          int commonFuncStuffB() {
              // Commonly used stuff 
          }
      };
      
    3. Provide implementations of the interface in the finally derived 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
          }
      };