C++ design class can not be inherited method examples

  • 2020-04-02 01:58:26
  • OfStack

The first thing that comes to mind is that in C++, the constructor of a subclass automatically calls the constructor of the superclass. Similarly, the destructor of the subclass will automatically call the destructor of the parent class. To make a class uninheritable, you simply define both its constructor and destructor as private functions. Therefore, when a class tries to inherit from it, it will inevitably cause compilation errors by trying to call the constructor and destructor.

However, since the constructor and destructor of this class are private functions, how can we get an instance of this class? You can create and release instances of classes by defining static. Based on this idea, you can write the following code:


///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public :
      static FinalClass1* GetInstance()
      {
            return new FinalClass1;
      }

      static void DeleteInstance( FinalClass1* pInstance)
      {
            delete pInstance;
            pInstance = 0;
      }

private :
      FinalClass1() {}
      ~FinalClass1() {}
};

This class is not inherited, but always feel that it and the general class is not the same, it is also a bit inconvenient to use. For example, you can only get instances that are on the heap and not on the stack.

Is it possible to implement a class that has the same usage as a normal class except that it cannot be inherited? There is always a way, but it takes some skill. See the following code:


///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
template <typename T> 
class MakeFinal
{
      friend T;

private :
      MakeFinal() {}
      ~MakeFinal() {}
};

class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public :
      FinalClass2() {}
      ~FinalClass2() {}
};

This class is no different from a normal class in that you can create instances on the stack or on the heap. Although class MakeFinal < FinalClass2 > Both the constructor and destructor are private, but since the class FinalClass2 is its friend, MakeFinal is called in FinalClass2 < FinalClass2 > Both the constructor and destructor of the.

But when you try to inherit a class from FinalClass2 and create an instance of it, it's not compiled.


class Try : public FinalClass2
{
public :
      Try() {}
      ~Try() {}
};

Try temp;

Because the class FinalClass2 is MakeFinal from the class < FinalClass2 > Virtual inheritance, when the constructor of the Try is called, simply skips FinalClass2 and calls MakeFinal directly < FinalClass2 > Constructor. Unfortunately, Try is not MakeFinal < FinalClass2 > , so its private constructor cannot be called.

Based on the above analysis, a class that attempts to inherit from FinalClass2, once instantiated, will cause a compilation error, so FinalClass2 cannot be inherited. This satisfies the design requirements.

The final keyword is already available in C++11: it specifies that a virtual function of a class cannot be overridden by an inherited class of that class, or that a class becomes an uninheritable class (final class).


struct A
{
    virtual void foo() final;
};

struct B final : A
{
    void foo(); // Error: foo cannot be overridden as it's final in A
};

struct C : B // Error: B is final
{
};


Related articles: