您的位置:首页 > 编程语言 > C语言/C++

C++ 创建一个不能被继承的类

2015-03-18 15:24 405 查看
一、分析

在Java中定义了关键字final,被final修饰的类不能被继承。但在C++中没有final这个关键字。

首先想到的是在C++ 中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。

可是这个类的构造函数和析构函数都是私有函数了,我们怎样才能得到该类的实例呢?

通过定义静态来创建和释放类的实例。

二、实现

下面是一个单例模式的实现

#include <iostream>
using namespace std;

class Singleton
{
private:
Singleton() {};
~Singleton() {};
static Singleton *instance;
public:
static Singleton* GetInstance()
{
if (instance == NULL)
{
instance = new Singleton();
}
return instance;
}

static void DeleteInstance()
{
if (instance != NULL)
{
delete instance;
instance = NULL;
}
}
};

Singleton* Singleton::instance=NULL;//一定要初始化(由于不能在方法体内部初始化,所以就放到外部)

int main()
{
Singleton *f = Singleton::GetInstance();//不能使用Singleton *f = new Singleton;创建对象
cout<<f<<endl;//而且是在堆上创建的对象,在函数GetInstance()使用new运算符,new在堆上分配内存

Singleton::DeleteInstance();

return 0;
}

这个类是不能被继承,但在总觉得它和一般的类有些不一样,使用起来也有点不方便。比如,我们只能得到位于堆上的实例,而得不到位于栈上实例。

能不能实现一个和一般类除了不能被继承之外其他用法都一样的类呢?办法总是有的,不过需要一些技巧。请看如下代码:

#include <iostream>
using namespace std;

class MakeFinal
{
friend class FinalClass2;
private:
MakeFinal() {}
~MakeFinal() {}
};

class FinalClass2 : virtual public MakeFinal
{
public:
FinalClass2() {}
~FinalClass2() {}
};

int main()
{
FinalClass2 *pFinalClass2 = new FinalClass2;//在堆上创建对象
FinalClass2 stack_object;//在栈上创建对象

cout<<pFinalClass2<<" "<<&stack_object<<endl;

return 0;
}

结果输出为:





很明显这两个对象是在不同的内存区域创建的。

这个类使用起来和一般的类没有区别,可以在栈上、也可以在堆上创建实例。尽管类MakeFinal的构造函数和析构函数都是私有的,但由于类FinalClass2是它的友元函数,因此在FinalClass2中调用MakeFinal的构造函数和析构函数都不会造成编译错误。

但当我们试图从FinalClass2继承一个类并创建它的实例时,却不能通过编译。

class Try : public FinalClass2

{

public:

Try() {}

~Try() {}

};

Try temp;

由于类FinalClass2是从类MakeFinal 虚继承过来的,在调用Try的构造函数的时候,会直接跳过FinalClass2而直接调用MakeFinal的构造函数。非常遗憾的是,Try不是MakeFinal的友元,因此不能调用其私有的构造函数。

基于上面的分析,试图从FinalClass2继承的类,一旦实例化,都会导致编译错误,因此是FinalClass2不能被继承。这就满足了我们设计要求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: