不能被继承的类,首先得知道如何使得一个类无法继承:子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误,从而可以完成一个不能被成的类,但是又为了让这个类可以正常的生成对象,则使其暴露静态的申请接口即可。但是同样的会导致一个问题,我们完成了第二个问题:只能在堆上创建对象
//只能在堆上创建对象
class A
{
public :
static A* GetInstance()
{
return new A;
}
static void DeleteInstance( A* pInstance)
{
delete pInstance;
pInstance = 0;
}
private :
A() {}
~A() {}
};
而有一种做法更加巧妙,通过友元使子类A可以访问基类调用析构和构造,但当子类A在进行继承时,A的子类不是最基类的友元,因此不能调用析构和构造,使得编译错误。
//不能被继承的类
template <typename T>
class Base
{
friend T;
private:
Base() {}
~Base() {}
};
class A : virtual public Base<A>
{
public:
A() {}
~A() {}
};
当然设计一个类只能在堆上创建对象还可以通过直接私有析构函数达到,因为在编译器发现一个类析构不可调用则会直接导致编译错误。
//在栈上创建时会报错(只能在堆上创建)
class A
{
public:
A(){}
void destory(){
delete this;
}
private:
~A(){}
};
最后设计一个类只能在栈上创建对象,即不能通过new生成对象,直接将重载的new变为私有,保证无法通过new创建即可
//在堆上创建时会报错(只能在栈上创建)
class A
{
private:
void *operator new(size_t t){}// 注意函数的第一个参数和返回值都是固定的
void operator delete(void* ptr){}// 重载了new就需要重载delete
public:
A(){}
~A(){}
};