首页 > 解决方案 > 禁止孩子调用父母的抽象(或虚拟)函数

问题描述

我有一个调用抽象回调的父类。子类旨在覆盖此回调,但绝不能从其代码中单独调用它。

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?
 } 

有很多这样的回调。我不希望用户迷路并认为他应该手动调用其中任何一个。

是否可以防止这些回调被子类调用?

标签: c++

解决方案


我认为没有办法在编译时强制执行您想要的规则,但是您可以在运行时通过断言失败来强制执行它们,这是次优的,因为至少任何违反规则的人都会学习他们下次运行程序时的方式错误。请注意,我添加了一个要求,即 MyCallback() 的子类覆盖必须只调用一次超类方法,以防止子MyCallback()类在允许回调的上下文中无故对自己或其超类进行额外调用.

#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;
}

推荐阅读