如何设计一个不可被继承的类?下面有三种方法,其中第二种方法很巧妙,在第三种方法出现之前,第二种方法应该是很好的解决办法了。
1. 粗糙的方法
为了让类不能够被继承,一个办法就是使得子类不能构造父类的部门,也就是子类无法实例化整个类。在C++中子类构造函数会自动调用父类的构造函数,子类的析构函数也会调用父类的析构函数,所以紫瑶吧类的构造函数和析构函数都定义为私有类型即可达到目的。
但是问题来了:如何构造类对象本身?此时可以通过定义静态成员函数来创建和释放类的实力:
代码如下:
class FinalClass
{
public:
static FinalClass* Construct(int n)
{
FinalClass* p=new FinalClass;
p->val=n;
return p;
}
static void Deconstruct(FinalClass* p)
{
delete p;
p=0;
}
void test(void)
{
cout<<"val= "<<val<<endl;
}
private:
FinalClass() {}
~FinalClass() {}
int val;
};
当我们试图继承这个类回发生什么?
显然试图访问基类的构造函数,但是因为被声明为private了,所以会报错。
这个方法有个很明显的缺点:无法再栈上构造类对象,全是在堆上得到的实例,需要程序员手动去释放。那么有没有第二种方法呢?
. 巧妙的设计
相处这个办法的人一定深谙对象设计,直接贴代码
class MakeFinal
{
friend class FinalClass2;
private:
MakeFinal() {}
~MakeFinal() {}
};
class FinalClass2 : virtual public MakeFinal
{
public:
FinalClass2()
{
cout<<"FinalClass2"<<endl;
}
~FinalClass2();
};
因为FinalClass2是类MakeFinal的的友元类,所以它可以访问MakeFinal的私有成员,所以
可以狗仔FinalClass类的实力对象,但是当我们试图从FinalClass2派生时,
class Test:public FinalClass2
{
public:
Test() {}
~Test() {}
};
会出现编译错误,MakeFinal的私有成员无法访问。因为FinalClass2是从MakeFinal虚继承过来的,Test无法借助FinalClass2来构造MakeFinal的数据,所以在Test的构造函数调用时,会直接跳过FinalClass2,而直接调用MakeFinal的构造函数,但Test类不是MakeFinal的友元类,所以无法访问MakeFinal的构造函数,所以无法实例化,因此FinalClass2无法被继承。
时代在进步,学过Java的都知道,java里面有一个final关键字,所以很方便的实现一个终端类,但是C++没有。但是随着C++11公布后增加了final这一关键字,也就是说直接在类的声明前面加final即可:
class A final
{
}
C++11变化很多,带来了很多有用的特效,C++也在借鉴其它语言的一些优秀的特性。