C++ 实现不允许继承的类
先从最简单的想法说起,把构造函数定义为Private那么此对象将没有办法创建当然也就没有办法被继承了,但这样的类定有什么意义呢?
/* 把构造函数作用域限定为私有那么这个类是没有办法被继承的,因为不能创建对象的实例 */ class NoHeirOne { private: NoHeirOne() { } };
我们让它变的有意义一些。为它提供一个方法去创建对象
/* 对NoHeirOne进行了改进,可以使用CreateInstance创建对象 */ class NoHeirTwo { public: static NoHeirTwo* CreateInstance(){ new NoHeirTwo(); } private: NoHeirTwo() { } };
这时候对象可以创建了。但有两个问题出现了,首先没有办法直接定义对象只能使用对象指针。其次的不直观且语义上定义模糊需要对调用者强调说明才能保证对象的正常释放。
NoHeirTwo NoH;//行不通了。不能直接使用 //可以这样使用,但从语义上来说破坏了对象的统一性,不再是new和delete一一对应了,而且没有直观的反应说明CreateInstance创建的对象一定要由调用者去释放。 NoHeirTwo* pNoH = NoHeirTwo::CreateInstance();
有个笑话说当一个对象简单到只有一个成员的时候那么可以使用union来定义,union可以有构造函数、析构函数也可以有方法当然数据成员却只有一个是有意义的。把union当成通常意义完备的类和对象是行不通的。而且union的成员不可以直接定义对象,比如说string没有办法定义为其成员,仅可以使用POD类型(可以理解为传统的C数据类型)。
C++之父Bjarne Stroustrup为我们提供了解决方案,代码如下
class Usable; class Usable_lock { friend class Usable; private: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; class Usable : public virtual Usable_lock { // ... public: Usable(); Usable(char*); // ... }; Usable a; class DD : public Usable { }; DD dd; // error: DD::DD() cannot access // Usable_lock::Usable_lock(): private member
其实现核心是使构造函数作用域定义为private,并且使用虚继承和友元类,从一个虚继承的类派生子类,不管继承层次有多深最终的子类必须调用祖先类的构造函数,因为其祖先必须显视初始化。由于祖先类构造函数是private那么子孙类是无法实现继承的。同时这个类又是语义和定义上都完备的类。OK现在终于有了想要的效果。