在Java中,如果用final修饰变量,则相当于c++中的const。但是final还可以修饰类和函数。当用来修饰类时,则表示类不能被继承, 而c++语言本身就没有这方面的功能。下面我会先给出解决方案,然后就其内部原理等展开进一步的讨论。因为水平有限,难免有错,还请大家指正。
方法一, 将构造函数声明为private
class NoDerivable
{
private:
NoDerivable();
... ...
public:
static NoDerivable* Create();
... ...
};
class TestClass : public NonDerivable
{
TestClass(){};//编译无法通过
//...
};
这是最简单的方法,但缺点是不能用new来直接创建类的实例,必须添加一个工厂方法,通过该方法来创建类的实例。
方法二,利用虚继承
class NonDerivableBase
{
private:
NonDerivableBase(){}
friend class NonDerivable;
};
#define FINAL_CLASS : private virtual NonDerivableBase
class NonDerivable FINAL_CLASS
{
//... some code here
};
class TestClass : public NonDerivable
{
TestClass(){};//编译无法通过
//...
};
首先,必须对NonDerivableBase是虚继承,
是否是private不重要。这种方法的问题是,必须为每个final 类定义一个base类。不过我们可以利用模板技术来进行改进。具体实现如下:
最终解决方案:
template<typename T>
class NonDerivableBase
{
private:
NonDerivableBase(){}
friend class T;
};
#define FINAL_CLASS (T) : private virtual NonDerivableBase<T>
class NonDerivable FINAL_CLASS(NonDerivable)
{
//... ...
};
class TestClass : public NonDerivable
{
TestClass(){};//编译无法通过
//...
};
个人认为这是最完整的解决方案,如果谁还有更好的建议,欢迎讨论。
进一步讨论:
问题一,为什么是虚继承?
大家肯定会注意到,上面的方法用到了虚继承。那不用虚继承是否可以呢?答案当然是不可以,这个大家可以自己去试。为什么呢?如果你对C++的内存对象模型有所了解的话,应该比较容易理解。下面简单说一下。
如果是普通继承,父类对象(通常称为subobject)是包含在子类对象中的,所以构造函数的调用也是TestClass的构造函数调用NonDerivable的构造函数,再由NonDerivable调用NonDerivableBase的构造函数,以上调用都不存在访问权限的问题,也就不能防止NonDerivable被继承。
而对于虚继承,需要确保最上层的类被实例化一次,因此当构造一个子类(TestClass)对象时,会先在内存中生成一个最上层类(NonDerivableBase)的对象,而TestClass 无权访问NonDerivableBase的private的构造函数,因此会编译不过。
问题二,为什么一定要用友元?
用友元是为了让NonDerivable自己能够实例化。我还在网上看到有一个不用友元的方法:
namespace Private
{
class
NonDerivableBase
{
public:
//NonDerivableBase(){}
NonDerivableBase(int){}//ADDED CTOR ARGUMENT
};
}
#define FINAL_CLASS : private virtual Private::NonDerivableBase
{
public:
NonDerivable() : NonDerivableBase(0) {} //PASS A DUMMY VALUE
};
实际上,这个方法是有问题的。因为我们可以这样来实现子类
class TestClass : public NonDerivable, private virtual Private::NonDerivableBase
{
public:
TestClass(): NonDerivableBase(0) {};
};
本文介绍了两种在C++中防止一个类被继承的方法:一是将构造函数设为私有并提供静态工厂方法;二是利用虚继承和友元类机制。深入探讨了这两种方法的工作原理及其优缺点。

4836

被折叠的 条评论
为什么被折叠?



