How to write my virtual functions cleanly

Viewed 89

I am fairly new to c++ and learning how to write clean code. I want to rewrite the function manage() in derived1mngr and derived2mngr class below. The code is common to both functions, only difference is the objecytype used to call the code. I do not want to replicate the same code in derived1mngr and derived2mngr. Any suggestions would help? How can i group the code together in base class manage ?

class Base{
    public:
    virtual void handle(){
        cout<< "handle base";
        ....//do something
    }
    void fn1() {...}
    .....
    void fn10() {...}
};

 class D1: public Base{
    public:
    void handle(){
        Base::handle();
        cout<< "D1 handle";
        ....//do something
    }
};
class D2: public Base{
    public:
    void handle(){
        Base::handle();
        cout<< "D2 handle";
        ....//do something
    }
};

class basemngr {
    public:
        virtual void manage() {
        }
        void callA() {....};
        void callB() {...};
};

class derived1mngr: public basemgr{
    public:
      void manage() {
          D1 d1;
          d1.handle();
          d1.fn1();
          d1.fn2();
          if ( d1.fn3()) {
              callA(); 
          }
         if ( d1.fn4()) {
              callB(); 
          }
        }
};

class derived2mgr{
    public:
          void manage() {
              D2 d2;
              d2.handle();
              d2.fn1();
              d2.fn2();
              if ( d3.fn3()) {
                  callA(); 
             }
             if ( d2.fn4()) {
                  callB(); 
             }
        }
};

int main ()
{
     basemgr* d1m = new derived1mgr();
     d1m-> manage();
}
2 Answers

Something along these lines, perhaps:

class basemngr {
    public:
        virtual void manage() {
        }
        void manageImpl(Base& b) {
          b.handle();
          b.fn1();
          b.fn2();
          // ...
        }
        void callA() {....};
        void callB() {...};
};

class derived1mngr: public basemgr{
    public:
      void manage() {
          D1 d1;
          manageImpl(d1);
     }
};

Generally speaking, inheritance with virtual functions is not for code reuse. Templates are.

This case screams for a template because as you point out the functions are the same except for the type used.

template <typename D, typename M>  
inline void manage(M& mngr) {
  D d;
  d.handle();
  d.fn1();
  d.fn2();
  if (d1.fn3()) {
    mngr.callA(); 
  }
  if (d.fn4()) {
    mngr.callB(); 
  }
}

This free function can then be called like this:

derived2mgr mngr;
manage<D2>(mngr);

Note that you can improve on this, by specifing the D type each class wants to use:

class MyMngr {
  public:
    using D = D3;
    /* ... */
};

Which would allow us to rewrite the function and remove the need to state which D type to use explicitly -> Less chance to make a mistake.

template <typename M>  
inline void manage(M& mngr) {
  typename M::D d;
  // ...
}
Related