Автоматический вызов функций базового класса

Я пытаюсь разобраться в некоторых более продвинутых точках классов C++, а также в возможных (или, по крайней мере, в GNU) компиляторах/встроенных функциях. Все из которых основано на концепции лесопогрузчика для (большого и обширного) рабочего проекта . Что подводит меня к этому psuedo-коду:

class Base {
     public:
           void increment(){
               ++m_Val;
           }
     private:
           static int m_Val;
};
class Above : private Base{
     public:
           void doA(){
                //Foo
           }
           void doB(){
               //Bar
           }
};

Это было показано как концепция; есть ли способ, чтобы простое наследование базы позволяло doA()и doB()неявно вызывать базовую функцию increment()без меня на самом деле добавляя вызов функции increment()в каждой отдельной функции каждого отдельного класса, который наследует ее? Если нет прямого ответа, есть ли конкретный термин для того, что я хочу сделать, называется? Или он предлагается в составе Boost или других библиотек?

3 ответа

  1. Одним из способов достижения подобного эффекта является предоставление метода для переопределения и предоставления другого общедоступного метода, вызывающего предварительные условия и постусловия.

    class Base {
         public:
               void increment(){
                   ++m_Val;
                   std::cout << m_Val << '\n';
               }
               void doA(){
                    increment();
                    implA();
               }
               void doB(){
                   increment();
                   implB();
               }
        protected:
            virtual void implA() = 0;
            virtual void implB() = 0;
    
         private:
               int m_Val;
    };
    class Above : private Base{
        public:
        using Base::doA;
        using Base::doB;
         protected:
            virtual void implA() override {
                std::cout << "a\n";
            }
            virtual void implB() override {
                std::cout << "b\n";
            }
    };
    
    int main()
    {
        Above a;
        a.doA();
        a.doB();
    }
    

    Демонстрация

  2. Вам придется явно определить, когда вы хотите, чтобы ваш базовый метод был вызван, но это может быть сделано путем абстрагирования вызова increment-попробуйте что-то вроде этого шаблона ( псевдо-код, используя терминологию Java, поскольку я не так хорошо знаком с эквивалентным синтаксисом C++, но вы должны получить суть его):

    abstract class Base {
         public:
               void increment(){
                   ++m_Val;
               }
               void doA(){
                    increment();
                    doAInternal();
               }
               void doB(){
                   increment();
                   doBInternal();
               }
         protected: 
               abstract void doBInternal();
               abstract void doAInternal();
         private:
               static int m_Val;
    };
    class Above : private Base{
         public:
               void doAInternal(){
                    //Foo
               }
               void doBInternal(){
                   //Bar
               }
    };
    
  3. После того, как наткнулся на это по чистой случайности; решение, которое наиболее близко напоминает то, что я ищу, называется «Execute-Around pointer», как определено здесь . В частности, раздел, касающийся:

    Часто необходимо выполнить функциональность до и после каждого вызова функции-члена класса.

    Который представлен на следующем фрагменте кода, взятом из упомянутой ссылки.

    class VisualizableVector {
      public:
        class proxy {
          public:
            proxy (vector<int> *v) : vect (v) {
              std::cout << "Before size is: " << vect->size ();
            }
            vector<int> * operator -> () {
              return vect;
            }
            ~proxy () {
              std::cout << "After size is: " << vect->size ();
            }
          private:
            vector <int> * vect;
        };
        VisualizableVector (vector<int> *v) : vect(v) {}    
        proxy operator -> () {
           return proxy (vect);
        }
      private:
        vector <int> * vect;
    };
    int main()
    {
      VisualizableVector vecc (new vector<int>);
      //...
      vecc->push_back (10); // Note use of -> operator instead of . operator
      vecc->push_back (20);
    }