This topic is derived from an interview question. I have checked many explanations on the Internet! I sorted it out myself and chose a solution that I thought was the best!
Let's start from the simplest:
First, we all know that to prevent the class from being instantiated, we can declare the default constructor by using the private or protected keyword. This technique is required to prevent classes from being inherited. Second, to prevent a class from being inherited, you also need to use private to control the inherited base class.
Namespace Sampleprivate
{
# Ifdef ndebug
Class Sealed
{
Protected :
Sealed () {} ;
Friend Class Samplesealedclass; // Set a friend class to access the sealed constructor.
} ;
Class Samplesealedclass: Private Virtual Sealed
{
} ;
# Else
Class Samplesealedclass {}
# Endif
}
In this way, we can instantiate samplesealedclass without worrying about being inherited. But I still need to explain why inheritance is blocked?
When we write the followingCodeWhat does the compiler do during compilation?ClassSubclass:PublicSamplesealedclass
{
};
First, when you instantiate subclass, you will first call the constructor of samplesealedclass, and before that, you will call the default constructor of the sealed class, however, we found that sealed cannot be instantiated, and the inheritance through private virtual can only be called by samplesealedclass, which effectively prevents the class from being inherited. However, only one class can be inherited. Is there a better way to prevent any class from being inherited?
The template is required: # Ifdef ndebug
Namespace Sealedclasses
{
Class Sealed
{
Protected:
Sealed (){}
} ;
Template < Class T > Class Typewapper
{
Public:
Typedef T type;
} ;
}
Template < Typename t > Class Basesealed: Private Virtual Sealedclasses: sealed
{
FriendClassSealedclasses: typewapper<T>: Type;
} ;
# Else
Template < Typename t > Class Basesealed
{
} ;
# Endif
The typewapper mainly transmits the external type to sealedclasses to obtain the ability to access the sealed constructor. However, this code is compiled in gcc4.0, but not in vs2008. It can be referenced as follows: Class Subclass: basesealed < Subclass >
{< br> Public :< br> subclass () { cout " subclass " Endl ;}
} ;
// The compilation below will fail.
Class Ssubclass: Public Subclass
{< br> Public :< br> ssubclass () { cout " ssubclass " Endl ;}
} ;