Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forbid child from invoking parent's abstract (or virtual) function

Tags:

c++

I have a parent class that invokes a callback that is abstract. The child class is meant to override this callback, but must never call it on its own from its code.

class Parent(){
   public:
   void Init(){ MyCallback(); }

   protected:
   virtual void MyCallback() = 0;//child must override, but child must never call it manually.
};


 class Child : public Parent{
     protected:
     void MyCallback()override{  }

     private:
     void SomeCode{ MyCallback(); }//<---how to prevent this?
 } 

There are many callbacks such as these. I don't want the user to get lost and think that he should call any of them manually.

Is it possible to prevent these callbacks from being invoked by child class?

like image 840
Kari Avatar asked Nov 30 '25 17:11

Kari


1 Answers

I don't think there is a way to enforce the rules you want at compile-time, but you can enforce them at runtime via assertion-failures, which is the next-best thing, since at least anyone who breaks the rule will learn the error of their ways the next time they run the program. Note that I've added a requirement that the subclass-overrides of MyCallback() must call up to the superclass-method exactly once, to prevent subclasses from gratuitously making additional calls to MyCallback() on themselves or their superclasses inside the callbacks-are-allowed context.

#include <stdio.h>
#include <stdlib.h>

class Parent
{
public:
   Parent() : _okayToCallCount(0), _numParentClassCallsMade(0) {/* empty */}

protected:
  virtual void MyCallback() 
  {  
     if (_okayToCallCount == 0) {printf("MyCallback() was called from an invalid context!\n"); abort();}
     _numParentClassCallsMade++;
     if (_numParentClassCallsMade > 1) {printf("Parent::MyCallback() was called more than once from the subclass's override-method!\n"); abort();}
  }   

private:
   // This is the only place that MyCallback should EVER be called from!
   void TheOnlyPlaceThatMyCallbackShouldEverBeCalledFrom()
   {  
      _numParentClassCallsMade = 0;

      _okayToCallCount++;
      MyCallback();
      _okayToCallCount--;

      if (_numParentClassCallsMade < 1) {printf("Parent::MyCallback() was never called from the subclass's override-method!\n"); abort();}
   }

   int _okayToCallCount;
   int _numParentClassCallsMade;
};

class Child : public Parent
{
public:
    Child() {}

    void SomeCode() { MyCallback(); }//<---how to prevent this?

protected:
    virtual void MyCallback()
    {  
       Parent::MyCallback();  // REQUIRED!
    }
};

int main(int argc, char ** argv)
{
   Child c;
   c.SomeCode();

   return 0;
}
like image 187
Jeremy Friesner Avatar answered Dec 02 '25 06:12

Jeremy Friesner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!