vendredi 15 mars 2019

Abstract parent class calling a pure virtual method implementation of child (c++)

Let me explain the somewhat confusing title.

The question is about abstract base classes and pure virtual method (implementations). I understand so far that:

  • A class is abstract if it contains at least one pure virtual method (which can have an implementation in Base. One often makes the constructor of such a class protected.
  • A Child : Base class must implement all pure virtual methods to become instantiatable.

I was trying to build an abstract base class that, by design of its methods and pure virtual methods, defines a certain process (which will never change in its basic routine), parts of which will change depending on the child class implementations. I was hoping to realize a design somewhat like the follwing:

class Base {
protected:
    Base() {
        setup();
    }
    virtual ~Base() {}
    void setup() {
        //do stuff that will always be the same
        setupDetails();
    }
    virtual void setupDetails() = 0;
    void mainProcess() {
        //do stuff that will always be the same
        processDetails();
    }
    void processDetails() = 0;
};
inline void Base::setupDetails() {} (**)
inline void Base::processDetails() {}


class Child : public Base {
private:
    Child() : Base() {}
    virtual ~Child() {}
    void setupDetails() {//do child stuff}
    void processDetails() {//do child stuff}
};

In my concrete case of application, Base is some "Quiz" class which provides a gui and a mechanism to ask questions in certain time intervals etc. The Child classes provide the actual questions/answers etc.

The provided design (at least to my naive mind) would force child classes to implement certain process steps which is otherwise not subject to change. However, this concept does not work, because "pure virtual functions are being called" in Base.

  • I would have to do it the other way around: Having the child classes build the process by using the base class methods (which I don't want!)
  • Or make the base class non-abstract by not marking the xxxDetails() methods pure, but simply virtual.

However: Although it seems logical that Base can't call a Childs methods, I still wonder... Base knows that a instantiatable Child MUST implement its pure virtual functions! And Base will only ever be instantiated when there is such a Child which means that there indeed IS an implementation. What's the problem? And how can I get the design I want? (*)

Or does the problem only arise because there is such a pure virtual method call in the constructor of Base, because the "first child" might as well be abstract itself?

(*) Maybe there is a big flaw in my whole notion of this problem, please enlighten me, then...

(**) These empty implementations prevent the "pure method call" error (?) but of course the parent methods are called, not the ones of the child.

Aucun commentaire:

Enregistrer un commentaire