Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Extend a reset function from a base class in a derived class

I have the following classes with a "reset" functionality.
The base class resets some things which are for all derived classes the same. This code should stay in the base class, so new childs don’t have to reimplement it.
The derived class must implement its own reset function where it can put reset-code which is specific for this derived class.

#include <iostream>
class Base
{
  public:
    Base(){}
    virtual ~Base()
    {
      std::cerr << __FUNCTION__ << std::endl;
      resetBase();
    }
    virtual void reset() = 0;
  protected:
    void resetBase()
    {
      // reset actions which are the same for all derived classes
      std::cerr << "Base::" << __FUNCTION__ << std::endl;
    }
};

class A : public Base
{
  public:
    A(){}
    ~A()
    {
      std::cerr << __FUNCTION__ << std::endl;
    }
    void reset() override
    {
      resetBase();
      std::cerr << "A::" << __FUNCTION__ << std::endl;
      // reset actions which are specific for this derived class
      mValueA = -1;
    }
  private:
    int mValueA = 0;
};

int main()
{
  Base* a = new A{};
  a->reset();
  delete a;
}

Output:

Base::resetBase
A::reset
~A
~Base
Base::resetBase

The code works, but I’m unsatisfied with the design.
I see the following problems:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  • If objects are deleted, only the resetBase() function is called. This is currently not so bad, since the objects are destroyed anyway. But it would be nicer if the reset function from the derived class would be called automatically anyway.
  • Every new child class has to make sure to call resetBase() in its reset() function. It would be nice if this happens automatically.

Is there a better way to extend a base reset functionality?

>Solution :

We can change your design to automate the resetBase() call using the "non-virtual interface" (NVI) idiom.

The NVI idea is to make the interface of a class non-virtual and then delegate to one or more pure virtual functions for the implementation, allowing the base class to ensure some invariant or common code is always executed, without requiring derived classes to remember to do so and stuff.

Appllying this idea in your case:

#include <iostream>

class Base
{
public:
    Base() {}
    virtual ~Base()
    {
        std::cerr << __FUNCTION__ << std::endl;
        resetBase();
    }
    void reset()
    {
        resetBase();
        doReset();
    }
protected:
    virtual void doReset() = 0;
private:
    void resetBase()
    {
        std::cerr << "Base::" << __FUNCTION__ << std::endl;
    }
};

class A : public Base
{
public:
    A() {}
    ~A()
    {
        std::cerr << __FUNCTION__ << std::endl;
    }
protected:
    void doReset() override
    {
        std::cerr << "A::" << __FUNCTION__ << std::endl;
        mValueA = -1;
    }
private:
    int mValueA = 0;
};

int main()
{
    Base* a = new A{};
    a->reset();
    delete a;
    return 0;
}

The common resetBase() code is always run and the derived classes only have to implement resetImpl() for their specific reset functionality. Also the destructor of the base class doesn’t need to call resetBase() any longer.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading