Как написать мои виртуальные функции чисто

#c #c 17

#c #c 17

Вопрос:

Я довольно новичок в c и учусь писать чистый код. Я хочу переписать функцию manage() в классах derived1mngr и derived2mngr ниже. Код является общим для обеих функций, единственное отличие заключается в objectytype, используемом для вызова кода. Я не хочу копировать один и тот же код в derived1mngr и derived2mngr. Любые предложения помогут? Как я могу сгруппировать код вместе в базовом классе 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();
}
  

Комментарии:

1. Я не понимаю смысла derivedXmgrs, поскольку каждый интерфейс реализован в basemgrs. Почему бы просто не использовать basemgrs и не принять базовый параметр. Есть ли какая-либо причина, по которой вам нужно разрешить классу mgr создавать экземпляр объекта?

Ответ №1:

Возможно, что-то в этом роде:

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

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

Комментарии:

1. Tadetnik b.handle() — это виртуальный вызов.

2. @новичок И …? Каким образом этот факт влияет на предлагаемое решение, по вашему мнению?

Ответ №2:

Вообще говоря, наследование с виртуальными функциями не предназначено для повторного использования кода. Шаблоны есть.

Этот случай требует шаблона, потому что, как вы указали, функции одинаковы, за исключением используемого типа.

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

Затем эта бесплатная функция может быть вызвана следующим образом:

 derived2mgr mngr;
manage<D2>(mngr);
  

Обратите внимание, что вы можете улучшить это, указав D тип, который хочет использовать каждый класс:

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

Что позволило бы нам переписать функцию и устранить необходимость указывать, какой D тип использовать явно -> Меньше шансов совершить ошибку.

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