C++ 终结类

C++ 如何实现不能被继承的类,即终结类。Java 中有 final 关键字修饰,C# 中有 sealed 关键字修饰,在 C++11 出来之前还没有类似的关键字来修饰类实现终结类,需编程人员手动实现。但从 C++11 开始,提出了 final 关键字来申明终结类。

现在不通过 C++11 关键词 final,该如何实现一个不能被继承的类呢?由于任何派生类的对象在创建的时候,都必需在派生类的构造函数中调用父类的构造函数。所以,只要类的构造函数在子类中无法被访问,那么就阻止了该类被继承,实现终结类。

如果将一个类的构造函数声明为私有(private),可以阻止该类进一步派生,但是该类也无法直接实例化了,所以此方法行不通。注意,构造函数为 private 的类,无法直接实例化,但是可以被间接实例化。间接实例化方法是:类中定义一个公有的静态成员函数,由这个函数来完成对象的初始化工作。联想到 C++ 的单例模式 Singleton,也是用到了这个方法,C++ 的单例模式的实现见如下代码:

class CSingleton  
{
private:  
    CSingleton(){};   //构造函数是私有的  
    static CSingleton *m_pInstance;  
public:  
    static CSingleton * GetInstance()  
    {  
        if(m_pInstance == NULL)  //判断是否第一次调用
        {
			m_pInstance = new CSingleton();
        }
        return m_pInstance;  
    }  
};  

C++ 中实现不能被继承的类的最为有效安全方便的方法是使用“虚拟继承”。一个基类如果被虚拟继承,那么在创建它的孙子类的对象时,该基类的构造函数需要单独被调用。此时,如果该基类的构造函数在孙子类的构造函数中无法访问,那么就实现了基类的子类不能被继承。

利用虚拟继承的这种特性,我们可以设计出这样一个基类 FinalParent,它不定义任何数据成员,这样任何类从它派生并不会增加任何空间上的开销。将它的默认构造函数的访问权限设定为 protected,这样它自身不能产生任何实例,只能用作基类。一个使用基类 FinalParent 实现终结类的例子如下:

#include <iostream>
using namespace std;

class FinalParent
{
protected:
	FinalParent();
};

class FinalClass:private virtual FinalParent
{
public:
	FinalClass():num(1){};
	void show()
	{
		cout<<"num:"<<num<<endl;
	}
private:
	int num;
};

class FinalClassChild:public FinalClass
{
	int a;
public:
	FinalClassChild():a(0){};
};

int main(int argc,char* argv[])
{
	FinalClassChild f;	// 报错,无法访问FinalParent::FinalParent()
	return 0;
}

从程序中可以看出,当 FinalClassChild 试图继承 FinalClass 的时候,FinalClassChild 的构造函数中需要调用 FinalParent 的构造函数,而 FinalParent 的构造函数在 FinalClass 中已经变成了私有 private,不能被 FinalClassChild 的任何成员函数所访问,导致编译错误。所以,任何一个类,只要虚拟继承类 FinalParent,就不能被继承,从而简单、高效、安全地实现了终结类。


参考文献

[1] 陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.C8.4怎样编写一个不能被继承的类.P280-282

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值