用C++设计一个不克不及被持续的类
添加时间:2013-6-7 点击量:
在Java 中定义了关键字final,被final润饰的类不克不及被持续。
起首想到的是在C++中,子类的机关函数会主动调用父类的机关函数。同样,子类的析构函数也会主动调用父类的析构函数。要想一个类不克不及被持续,只要把它的机关函数和析构函数都定义为私有函数。那么当一个类试图从它那持续的时辰,必定会因为试图调用机关函数、析构函数而导致编译错误。
可是这个类的机关函数和析构函数都是私有函数了,如何才干获得该类的实例呢?可以经由过程定义静态来创建和开释类的实例。基于这个思路,可以写出如下的代码:
///////////////////////////////////////////////////////////////////////
// Define a class which cant be derived
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public :
static FinalClass1 GetInstance()
{
return new FinalClass1;
}
static void DeleteInstance( FinalClass1 pInstance)
{
pInstance;
pInstance = 0;
}
private :
FinalClass1() {}
~FinalClass1() {}
};
这个类是不克不及被持续,但在总感觉它和一般的类有些不一样,应用起来也有点不便利。比如,只能获得位于堆上的实例,而得不到位于栈上实例。
能不克不及实现一个和一般类除了不克不及被持续之外其他用法都一样的类呢?办法老是有的,不过须要一些技能。请看如下代码:
///////////////////////////////////////////////////////////////////////
// Define a class which cant be derived
///////////////////////////////////////////////////////////////////////
template <typename T>
class MakeFinal
{
friend T;
private :
MakeFinal() {}
~MakeFinal() {}
};
class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public :
FinalClass2() {}
~FinalClass2() {}
};
这个类应用起来和一般的类没有差别,可以在栈上、也可以在堆上创建实例。尽管类MakeFinal<FinalClass2>的机关函数和析构函数都是私有的,但因为类FinalClass2是它的友元函数,是以在FinalClass2中调用MakeFinal<FinalClass2>的机关函数和析构函数都不会造成编译错误。
但当试图从FinalClass2持续一个类并创建它的实例时,却不合经由过程编译。
class Try : public FinalClass2
{
public :
Try() {}
~Try() {}
};
Try temp;
因为类FinalClass2是从类MakeFinal<FinalClass2>虚持续过来的,在调用Try的机关函数的时辰,会直接跳过FinalClass2而直接调用MakeFinal<FinalClass2>的机关函数。很是遗憾的是,Try不是MakeFinal<FinalClass2>的友元,是以不克不及调用其私有的机关函数。
基于上方的解析,试图从FinalClass2持续的类,一旦实例化,都邑导致编译错误,是以是FinalClass2不克不及被持续。这就满足了设计请求。
C++11中已经有了final关键字:它的感化是指定类的虚函数不克不及被该类的持续类重写(override),或者是指定一个类成为一个不克不及被持续的类(final class)。
struct A
{
virtual void foo() final;
};
struct B final : A
{
void foo(); // Error: foo cannot be overridden as its final in A
};
struct C : B // Error: B is final
{
};
容易发怒的意思就是: 别人做了蠢事, 然后我们代替他们, 表现出笨蛋的样子。—— 蔡康永
在Java 中定义了关键字final,被final润饰的类不克不及被持续。
起首想到的是在C++中,子类的机关函数会主动调用父类的机关函数。同样,子类的析构函数也会主动调用父类的析构函数。要想一个类不克不及被持续,只要把它的机关函数和析构函数都定义为私有函数。那么当一个类试图从它那持续的时辰,必定会因为试图调用机关函数、析构函数而导致编译错误。
可是这个类的机关函数和析构函数都是私有函数了,如何才干获得该类的实例呢?可以经由过程定义静态来创建和开释类的实例。基于这个思路,可以写出如下的代码:
///////////////////////////////////////////////////////////////////////
// Define a class which cant be derived
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public :
static FinalClass1 GetInstance()
{
return new FinalClass1;
}
static void DeleteInstance( FinalClass1 pInstance)
{
pInstance;
pInstance = 0;
}
private :
FinalClass1() {}
~FinalClass1() {}
};
这个类是不克不及被持续,但在总感觉它和一般的类有些不一样,应用起来也有点不便利。比如,只能获得位于堆上的实例,而得不到位于栈上实例。
能不克不及实现一个和一般类除了不克不及被持续之外其他用法都一样的类呢?办法老是有的,不过须要一些技能。请看如下代码:
///////////////////////////////////////////////////////////////////////
// Define a class which cant be derived
///////////////////////////////////////////////////////////////////////
template <typename T>
class MakeFinal
{
friend T;
private :
MakeFinal() {}
~MakeFinal() {}
};
class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public :
FinalClass2() {}
~FinalClass2() {}
};
这个类应用起来和一般的类没有差别,可以在栈上、也可以在堆上创建实例。尽管类MakeFinal<FinalClass2>的机关函数和析构函数都是私有的,但因为类FinalClass2是它的友元函数,是以在FinalClass2中调用MakeFinal<FinalClass2>的机关函数和析构函数都不会造成编译错误。
但当试图从FinalClass2持续一个类并创建它的实例时,却不合经由过程编译。
class Try : public FinalClass2
{
public :
Try() {}
~Try() {}
};
Try temp;
因为类FinalClass2是从类MakeFinal<FinalClass2>虚持续过来的,在调用Try的机关函数的时辰,会直接跳过FinalClass2而直接调用MakeFinal<FinalClass2>的机关函数。很是遗憾的是,Try不是MakeFinal<FinalClass2>的友元,是以不克不及调用其私有的机关函数。
基于上方的解析,试图从FinalClass2持续的类,一旦实例化,都邑导致编译错误,是以是FinalClass2不克不及被持续。这就满足了设计请求。
C++11中已经有了final关键字:它的感化是指定类的虚函数不克不及被该类的持续类重写(override),或者是指定一个类成为一个不克不及被持续的类(final class)。
struct A
{
virtual void foo() final;
};
struct B final : A
{
void foo(); // Error: foo cannot be overridden as its final in A
};
struct C : B // Error: B is final
{
};
容易发怒的意思就是: 别人做了蠢事, 然后我们代替他们, 表现出笨蛋的样子。—— 蔡康永