class
实现一个不能被继承的类
- 2009-07-12
- mikzzz
1、方法一 将其构造函数声明为私有的
最直观的解决方法就是将其构造函数声明为私有的,这样就可以阻止子类构造对象了。但是这样的话,就无法构造本身的对象了,就无法利用了。
既然这样,我们又可以想定义一个静态方法来构造类和释放类。
#include<iostream>
using namespace std;
class A
{
public:
static A* Construct(int n)
{
A *pa = new A;
pa->num = n;
cout<<"num is:"<<pa->num<<endl;
return pa;
}
static void Destruct(A * pIntance)
{
delete pIntance;
pIntance = NULL;
}
private:
A(){}
~A(){}
public:
int num;
};
int main()
{
A *f = A::Construct(9);
cout<<f->num<<endl;
A::Destruct(f);
return 0;
}
2、方法二 利用友元不能被继承的特性,可以实现这样的类。
设计一个模板辅助类 Base,将构造函数声明为私有的;再设计一个不能继承的类 FinalClass,将 FinalClass 作为 Base 的友元类。FinalClass 虚继承 Base。
#include <iostream>
using namespace std;
template <typename T>
class Base{
friend T;
private:
Base(){
cout << "base" << endl;
}
~Base(){}
};
class FinalClass : virtual public Base<FinalClass>{
//一定注意 必须是虚继承
public:
FinalClass(){
cout << "FinalClass()" << endl;
}
};
class C : public FinalClass {
public:
C(){} //继承时报错,无法通过编译
};
int main(){
FinalClass b; //B类无法被继承
//C c;
return 0;
}
类 Base 的构造函数和析构函数因为是私有的,只有 Base 类的友元可以访问,FinalClass 类在继承时将模板的参数设置为了 FinalClass 类,所以构造 FinalClass 类对象时们可以直接访问父类(Base)的构造函数。
为什么必须是虚继承呢?
虚继承的功能是:当出现了菱形继承体系的时候,使用虚继承可以防止二义性,即子孙类不会继承多个原始祖先类。
那么虚继承如何解决这种二义性的呢?从具有虚基类的类继承的类在初始化时进行了特殊处理,在虚派生中,由最低层次的派生类的构造函数初始化虚基类。
结合上面的代码来解释:C 在调用构造函数时,不会先调用 FinalClass 的构造函数,而是直接调用 Base 的构造函数,C 不是 Base 的友元类,所以无法访问。这样的话 C 就不能继承 FinalClass。
注 C++11 的已经加入了 final 关键字,直接在类后面加上 final 关键字,就可以防止该类被继承。