C++ Forcing Method Override In Concrete Class

后端 未结 5 2355

Is there a way in C++ to write a concrete class which when another class is derived from it, has a method which must be overriden. An abstract class allows the forcing of the de

相关标签:
5条回答
  • 2021-02-20 06:39

    I will assume you are looking for a compile-time enforcing of this condition (thank you @Chad for pointing it out)

    There is no direct language-mechanism in C++ that I know of. I mean, there is not a reserved keyword to put in front of your method declaration that would achieve your desired goal.

    I think that what you say is pointing to a design problem in your software. Let's say you want to force the foo() method to be reimplemented by all inherirhing classes in the following snippet

    class BaseButConcrete
    {
        ... //Common stuff
        ... //
    
        virtual void foo()
        { /*implementation that you do not want to be inherited, but will be...*/ }
    }
    
    class DerivedOtherConcrete : public BaseButConcrete
    {
        void foo()
        { /*different implementation, 
          but no obligation from compiler point of view*/ }
    }
    

    I can see no good design reason why all the common stuff could not be moved in an abstract base class. From what you describe, you do not want to inherit the foo implementation in Derived, so do not inherit that part ! Thus the very classic design should do the trick :

    class AbstractBase
    {
        ... //Common stuff has moved here
        ... //
        virtual void foo() =0;
    }
    
    class NotAnymoreBaseButStillConcrete : public AbstractBase
    {
        void foo()
        { /*implementation that should not be inherited,
          and that will not by design*/ }
    }
    
    class DerivedOtherConcrete : public AbstractBase
    {
        void foo()
        { /*different implementation, 
          now mandatory compiler-wise for the class to be concrete*/ }
    }
    

    This way, the common stuff is still shared among all your derived classes, and you keep what you do not want to inherit (i.e. the foo implementation) separated in classes not on the same inheritance path.

    0 讨论(0)
  • 2021-02-20 06:41

    As others have mentioned you can "fix" this for one level of derivation, by splitting your current concrete class into an abstract class and a concrete class.

    The not uncommon generalization of that approach is to have a class template that must be used to create a concrete class out of each abstract class. For example, it could supply a clone method. Or, in Microsoft's ATL, it supplies IUnknown interface implementation.

    However, the abstract class hierarchy with auto-generated concrete leafs is in general too much work and complication. The practical approach is to instead just document what has to be overridden, like clone. You can't in general force other's code to be correct, you can only help it along in that direction.

    By the way, if you could be more concrete about your particular problem, then there could be far better answers than this general wishwash.

    However, by generalizing your problem, you generalized the answers.

    Cheers & hth.,

    0 讨论(0)
  • 2021-02-20 06:43

    No, it is not possible. If you want to enforce (in compile time) a derived class to define a virtual function then its base class needs to be abstract, or in other words the base class needs to have a pure virtual function. Abstract class (with pure virtual function(s)) cannot be concrete, i.e. you cannot instantiate it.

    0 讨论(0)
  • 2021-02-20 06:47

    Instead of defining intermediate classes, I find much more intuitive and clean leveraging on multiple inheritance. If our derived class inherits also from an abstract class which declares a pure virtual method with the same name as the one we want to force the override, then the compiler will not allow to instantiate objects of the derived type unless the method is actually overridden in the derived class.

    #include <iostream>
    
    struct Base{
      virtual void print() {std::cout << "Base" << std::endl; }  
    };
    
    struct RequireOverride {
      virtual void print() = 0;   
    };
    
    struct D1: Base, RequireOverride {
      virtual void print() {std::cout << "D1" << std::endl; }  
    };
    
    struct D2: Base, RequireOverride {
      // no override of function print() results in a compilation error
      // when trying to instantiate D2
    };
    
    
    int main() {
      D1 d1;
      d1.print(); //ok
    
    
      //D2 d2; // ERROR: cannot declare variable 'd2' to be of abstract type 'D2'
               // because the following virtual functions are pure within 'D2':
               // virtual void RequireOverride::print()
      return 0;
    }
    

    If you have multiple methods for which you want to enforce the existence of overrides, then you can put all of them in RequireOverride, or define more structures to multiple-inherit from, such as RequireOverrideMethod1, RequireOverrideMethod2, according to the context.

    0 讨论(0)
  • 2021-02-20 06:48

    One option is to put all the implementation of the class into an abstract superclass, and inherit from that instead.

    • Move all the implementation of your concrete class T into an abstract class S.
    • In S, make the must-be-overridden method a pure virtual function -- and provide a definition of it.
    • T subclasses S.
    • In T, override the must-be-overridden function, and call the S implementation.
    • Instead of subclassing T, subclass S.
    • Prevent subclassing of T.
    0 讨论(0)
提交回复
热议问题