在 C++ 中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。
template <typename T>
class A
{
friend T;
private:
A() {}
~A() {}
};
class B : virtual public A<B>
{
public:
B() {}
~B() {}
};
类B使用起来和一般的类没有区别,可以在栈上、也可以在堆上创建实例。尽管类 A<B> 的构造函数和析构函数都是私有的,但由于类B是它的友元函数,因此在B中调用 A<B> 的构造函数和析构函数都不会造成编译错误。
但当我们试图从B 继承一个类并创建它的实例时,却不同通过编译。
class C : virtual public B
{
public:
C() {}
~C() {}
};
由于类 B 是从类 A <B> 虚继承过来的,在调用 C的构造函数的时候,会直接跳过B而直接调用A<B> 的构造函数。非常遗憾的是,C 不是 A <B> 的友元,因此不能调用其私有的构造函数。
基于上面的分析,试图从 B 继承的类,一旦实例化,都会导致编译错误,因此是 B 不能被继承。这就满足了我们设计要求。
void main( void )
{
B b;
//C c;
return;
}
还有另一种思路,例如:
class TheOnlyInstance
{
publc:
static TheOnlyInstance* GetTheOnlyInstance()
{
return new TheOnlyInstance;
}
static void ReleaseTheOnlyInstance(TheOnlyInstance* pInstance)
{
delete pInstance;
pInstance = NULL;
}
private:
TheOnlyInstance(){}
~TheOnlyInstance(){}
}
这个类是不能被继承,但是我们只能得到位于堆上的实例,得不到位于栈上的实例。