0

For example, say I have a basic data object class as below.

class DataObject {
   protected:
      bool data_changed;
      virtual void save() {}
      virtual void load() {}
   public:
      virtual void idle() { 
          if (data_changed) {
              save();
              data_changed = false;
          }
      }
};

The idea is that "idle" is called periodically from some main looping thread and performs non-critical updates.

Now I want derived classes to be able to have their own idle functions. But I don't want to lose the default behavior.

One solution is to say "remember to call DataObject::idle() from overridden idle() functions".

Like this:

class ChildData : public DataObject {
   public:
      virtual void idle() override {
          //do something
          
          DataObject::idle(); //remember to call parent idle!
      }
};

But this is very dangerous as people can just forget.

Is there a way to enforce this somehow? Or make it automatic, like a virtual destructor?

(My current "workaround" is to have 2 functions, one the parent_idle that does the important stuff, and then one overridable child_idle that derived functions can override. But this is a bit messy, and also you have to make a whole new set of functions again if you want some child function to enforce its own default...)

CaptainCodeman
  • 1,951
  • 2
  • 20
  • 33
  • 1
    Rather use the [_Template Method Pattern_](https://sourcemaking.com/design_patterns/template_method). – πάντα ῥεῖ Apr 10 '22 at 08:58
  • Template Method Pattern, is basically what I described in my last paragraph by having multiple functions, is it not? – CaptainCodeman Apr 10 '22 at 09:04
  • It's about having public functions, which call pure virtual functions of derived classes with certain pre-/post-conditions. – πάντα ῥεῖ Apr 10 '22 at 09:07
  • This is a duplicate of e.g. https://stackoverflow.com/q/9724371/3740047. There is no C++ language feature to enforce that overridden functions call the base class version. The template method pattern is the best thing one can do, AFAIK. – Sedenion Apr 10 '22 at 09:41

1 Answers1

0

Maybe you could write it:

   ...
   void idle_start() {   // not virtual, main looping thread calls this
     idle();
     if (data_changed) {
        save();
        data_changed = false;
     }
   }
   virtual void idle() {   }  // virtual, noop by default
   ...

That depends if you want to have your derived behavior before the mandatory base behavior.

joao
  • 3,517
  • 1
  • 31
  • 43