是否有一种技术可以强制虚拟函数在所有派生类中重写?

时间:2017-11-29 02:34:28

标签: c++

考虑一下:

struct Base {
    virtual void fn() = 0;
};

struct A: Base {
    virtual void fn();
};

struct B: A {
    // fn is not overridden here
};

基本上,fnA中实施。 B来自A,而B并非覆盖fn

我希望有技巧让B必须覆盖fn,因为如果没有覆盖它就是错误。

可以这样做吗?编译时错误(或警告)是最好的,但如果不可能,那么运行时错误也是可以的。我想知道,如果有人忘记在派生类中覆盖fn

原因是什么? fn可以返回与课程相关的信息。例如,它可以返回类名。或者它可以返回对象使用的已分配空间量(用于调试目的)。或者做一些与课程相关的任务(例如,加载/保存其状态)。

1 个答案:

答案 0 :(得分:2)

如果fn未覆盖B,则无法强制编译器生成错误。

您可以稍微修改一下代码以获得所需内容。

  1. A::fn成为纯虚拟的。将实现保留为A中的实现。请记住,即使它被声明为纯虚拟,也可以实现A::fn

  2. 这会强制您覆盖fn中的BB::fn的实施可以根据需要使用尽可能多的A::fn

  3. truct Base {
        virtual void fn() = 0;
    };
    
    struct A : Base {
        virtual void fn() = 0;
    };
    
    void A::fn()
    {
       // Add implmentation details
    }
    
    struct B : A {
        // fn must be  overridden here
        virtual void fn();
    };
    
    void B::fn()
    {
       A::fn();
       // Add additonal logic for B
    }
    

    如果A::fn被称为on B对象,则可能会生成运行时错误。

    这是一种方法。

    #include <iostream>
    
    struct Base
    {
       virtual void fn() = 0;
    
       virtual int getTypeID() = 0;
    
       protected:
    
       static int getNextID()
       {
          static int nextid = 0;
          return ++nextid;
       }
    
       static int getClassTypeID()
       {
          static int id = getNextID();
          return id;
       }
    };
    
    struct A : Base 
    {
       virtual void fn();
    
       virtual int getTypeID()
       {
          return getClassTypeID();
       }
    
       private:
    
       static int getClassTypeID()
       {
          static int id = getNextID();
          return id;
       }
    };
    
    void A::fn()
    {
       if ( this->getTypeID() != A::getClassTypeID()  )
       {
          // Problem.
          std::cout << "ERROR. fn() called on a derived class object.\n";
       }
       else
       {
          std::cout << "OK. fn() called on an A object.\n";
       }
    }
    
    struct B : A
    {
       virtual int getTypeID()
       {
          return getClassTypeID();
       }
    
       static int getClassTypeID()
       {
          static int id = getNextID();
          return id;
       }
    };
    
    int main()
    {
       A* a1Ptr = new A;
       A* a2Ptr = new B;
    
       a1Ptr->fn();
       a2Ptr->fn();
    }
    

    输出:

    OK. fn() called on an A object.
    ERROR. fn() called on a derived class object.