面试:C++不可继承类
面试中可能遇到让设计一个无法被继承的类。最简单的实现是将该类的构造函数设置为私有的,然后通过静态成员函数调用私有构造函数实例化对象,这样的类确实不可继承,但是使用起来非常不方便,必须使用静态成员实例化对象,而且对象存储在堆中,无法像一个普通的类一样的被使用。最佳的设计是结合私有构造函、友元、虚拟继承实现。
一、简单实现
1 class Simple{ 2 private: 3 Simple(){}; 4 ~Simple(){} 5 private: 6 static Simple* getInstance(){ 7 return new Simple(); 8 } 9 static void deleteInstance(Simple* instance){ 10 delete instance; 11 } 12 };
二、最佳实现
1 template<typename T> 2 class NoneInherit { 3 friend T; 4 private: 5 NoneInherit() { 6 } 7 ~NoneInherit() { 8 } 9 }; 10 11 class Finalclass: virtual public NoneInherit<Finalclass> { 12 public: 13 Finalclass() { 14 } 15 ~Finalclass() { 16 } 17 }; 18 19 //class TestClass: public Finalclass { 20 //};
关键点:
- 模板类NoneInherit类,构造函数和析构函数都设置为私有,模板参数T设置为友元,这样友元类可以调用构造函数。例如FinalClass是NoneInherit的友元类,可以使用基类的私有构造函数和析构函数
- 虚拟继承virtual是最关键的点。如果继承时去掉virtual,FinalClass还是可以被继承的,那么为什么需要使用虚拟继承呢?因为在普通继承中,每个类只是初始化自己的直接的基类。那意味着,如果不使用virtual,TestClass继承Finalclass,由FinalClass再去调用NoneInherit类,由于FinalClass是NoneInHerit的基类,因此整个继承没有任何问题。由于FinalClass使用了虚拟继承,在创建TestClass的时候,TestClass类的构造函数要负责虚基类NoneInherit类的构造,而NoneInherit的构造函数是私有的,友元关系也无法继承,因此TestClass类没有访问的权限。