How to make the class unable to be inherited
If you are familiar with java, you should know that one type of java cannot be inherited, that is, the final class. this type is useful, especially in the inheritance hierarchy of control classes in large projects. so that the number of child classes does not explode. this is also a good way to prevent the occurrence of a diamond hierarchy in the use of multi-inheritance class layers. there are many methods to implement a class that cannot be inherited.
The main idea is to make the subclass unable to construct the part of the parent class, so that the subclass cannot instantiate the entire subclass. this restricts subclass inheritance. therefore, the constructor of the parent class can be declared as private, but the parent class cannot be instantiated. I want to add a static help function for construction. although this is very simple. but this is indeed a solution.
However, if only this method can be solved, C ++ is too inflexible, and it is not worth writing an article! Is there a way to solve the above problems?
We can take advantage of features that friends cannot inherit!
Assume that there is already a class CXX. this is a branch of a certain class level. Now we need to inherit a Final subclass CParent from CXX, that is, CParent cannot be inherited. we can make full use of the features that friends cannot inherit, that is, to make CParent a member and a subclass of a class, CParent can be constructed, however, the CChild subclass of CParent cannot inherit the member feature, so it cannot be constructed. so we introduce a CFinalClassMixin.
We expect the functions of this class as follows:
Any class inherited from it cannot be instantiated.
At the same time, we do not want this class to be instantiated.
How to implement this class? Very easy! That is to say, we can implement a class that both constructor and destructor are private. At the same time, we can declare our CParent as a member in this class. The Code is as follows:
[Cpp]
Class CFinalClassMixin
{
Friend class CParent;
Private:
CFinalClassMixin (){}
~ CFinalClassMixin (){}
};
// Our CParent code should be as follows:
Class CParent: publicCXXX
{
Public:
CParent (){}
~ CParent (){}
};
Class CFinalClassMixin
{
Friend class CParent;
Private:
CFinalClassMixin (){}
~ CFinalClassMixin (){}
};
// Our CParent code should be as follows:
Class CParent: publicCXXX
{
Public:
CParent (){}
~ CParent (){}
}; It is a class extended from CXXX (note, it can still be inherited at this time). Now we need it not to be inherited. Just change the code
[Cpp]
Class CParent: public CFinalClassMixin, public CXXX
{
Public:
CParent (){}
~> CParent (){}
};
Class CParent: public CFinalClassMixin, public CXXX
{
Public:
CParent (){}
~> CParent (){}
};
That's it. Now we can inherit a subclass from CParent.
Class CChild: public CParent {};
Compile the code and try to find that: It doesn't work !!
Now let's look back at the reason for this operation, that is, the principle of this solution, that is, to allow the parent class to access the constructor of the Mixin class, but not the subclass.
Now let's look at our code and find that the parent class is a member of the CFinalClassMixin class and can access its constructor. because friends cannot inherit, CChild cannot access the constructor of CFinalClassMixin. so it should not be instantiated.
CChild really cannot access the CFinalClassMixin constructor, but it does not have to call it! I think this is the cause of the problem. CChild uses CParent to construct CFinalClassMixin, so this member is of no use to him!
Now the problem has been found. It is easy to solve. As long as CChild needs to call the CFinalClassMixin constructor, how can this problem be achieved?
Do you still remember virtual inheritance? One feature of virtual inheritance is that the constructor of the virtual base class is constructed by the final subclass! Therefore, you can inherit CParent from CFinalClassMixin to CFinalClassMixin. The Code is as follows:
[Cpp]
Class CParent: virtual public CFinalClassMixin, public CXXX
{
Public:
CParent (){}
CParent (){}
};
Class CParent: virtual public CFinalClassMixin, public CXXX
{
Public:
CParent (){}
CParent (){}
};
Try it now.
However, some people may have a lingering worry about inheritance! But we don't have to worry so much here! Why? Because our CFinalClassMixin class is pure! Pure! That is to say, it has no member variable at all! We don't have to worry about the biggest problem of multi-inheritance. The data redundancy produced by diamond inheritance and its ambiguity.
There is still a problem! That is, we cannot add the comments to a class to the CFinalClassMixin class every time! So much trouble! Although it is not a big problem, I think it is still necessary to solve it, because I fully trust C ++!
The solution is also very simple! The template is used! The specific description is omitted. You can see the code at a glance.
Below is the complete code of my test program (the CFinalClassmixin has been changed to the template)
[Cpp]
// Finaltest. cpp: Defines the entry point for the console application.
//
# Include "stdafx. h"
# Include <iostream>
Using namespace std;
Template <class T>
Class CFinalClassMixin
{
Friend T;
Private:
CFinalClassMixin (){}
~ CFinalClassMixin (){}
};
Class CXXX
{
Public:
CXXX () {cout <"I am CXXX" <endl ;}
~ CXXX (){}
};
Class CParent: virtual public CFinalClassMixin <CParent>, public CXXX
{
Public:
CParent (){}
~ CParent (){}
};
Class CChild: public CParent {};
Int main (int argc, char * argv [])
{
CParent a; // can be constructed
// CChild B; // cannot be constructed
Return 0;
}
// Finaltest. cpp: Defines the entry point for the console application.
//
# Include "stdafx. h"
# Include <iostream>
Using namespace std;
Template <class T>
Class CFinalClassMixin
{
Friend T;
Private:
CFinalClassMixin (){}
~ CFinalClassMixin (){}
};
Class CXXX
{
Public:
CXXX () {cout <"I am CXXX" <endl ;}
~ CXXX (){}
};
Class CParent: virtual public CFinalClassMixin <CParent>, public CXXX
{
Public:
CParent (){}
~ CParent (){}
};
Class CChild: public CParent {};
Int main (int argc, char * argv [])
{
CParent a; // can be constructed
// CChild B; // cannot be constructed
Return 0;
}
Now you only need to add a CFinalClassMixin mixed class to the class you do not want to inherit as the parent class.
Author: w397090770