Home > Mobile >  What is a pattern to ensure that every derived class (including derived classes of the immediate der
What is a pattern to ensure that every derived class (including derived classes of the immediate der

Time:03-15

I have a base class and a number of generations of descendants (derived classes):

class Base{
    public:
    virtual void myFunc() = 0;
}
    
class Derived : public Base{
    //This class needs to implement myFunc()
}
    
class Derived2 : public Derived{
    //How to force this class to implement its version of myFunc(), and force it to call Derived::myFunc as well ?
}
    
class Derived3 : public Derived2{
    //.....should implement its own myFunc and call Derived2's mynFunc()...
}
    
class Derived4 : public Derived3{
    //.....should implement its own myFunc and call Derived3's mynFunc()...
}

Is there a pattern to ensure:

  • That each derived class (regardless of whether it is an immediate descendant of the base class, or a descendant of a descendant of the base class), implement its version of myFunc?
  • That each derived class calls its immediate parent class myFunc?

EDIT: The pattern that comes to mind to me is Decorator pattern, but wondering if there is some better way or variation.

CodePudding user response:

I propose the following solution:

#include <iostream>

template <class BaseClass>
class RequireMyFunc: public BaseClass
{
    public:
    virtual void myFunc() = 0; // declaration to force write implementation
    protected:
    void callBaseClassMyFunc() override
    {
        BaseClass::callBaseClassMyFunc();
        BaseClass::myFunc();
    }
};

class Base{
    public:
    void func()
    {
        callBaseClassMyFunc();
        //myFunc();
    }
    virtual void myFunc(){};
    protected:
        Base(){}
        virtual void callBaseClassMyFunc(){};
};
    
class Derived : public RequireMyFunc<Base>{
    public:
    void myFunc() override
    {
        std::cout << "Derived" << std::endl;
    }
};
    
class Derived2 : public RequireMyFunc<Derived>{
    public:
    void myFunc() override
    {
        std::cout << "Derived2" << std::endl;
    }
};
    
class Derived3 : public RequireMyFunc<Derived2>{
    public:
    void myFunc() override
    {
        std::cout << "Derived3" << std::endl;
    }
};

int main()
{
    Base* d = new Derived();
    d->func();  // prints "Derived" (invokes only Derived::myFunc)
    
    Base* d2 = new Derived2();
    d2->func(); // prints "Derived" and "Derived2", i.e. invokes Derived::myFunc and Derived2::myFunc
    
    Base* d3 = new Derived3();
    d3->func(); // prints "Derived", "Derived2" and "Derived3"
    
    d->myFunc(); // prints "Derived"
    d2->myFunc(); // prints only "Derived2"
    d3->myFunc(); // prints only "Derived3"
    
    // Base* b = new Base(); -- cannot create because of protected constructor
    //b->myFunc(); // prints nothing
}
  • Related