首页 > 代码库 > 剑指offer (48) c++实现一个不能被继承的类

剑指offer (48) c++实现一个不能被继承的类

题目:用c++实现一个不能被继承的类

 

题解分析:

 

常规解法:

首先想到的是在C++ 中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。

要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。

那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。

可是这个类的构造函数和析构函数都是私有函数了,我们怎样才能得到该类的实例呢?

这难不倒我们,我们可以通过定义静态函数来创建和释放类的实例。基于这个思路,我们可以写出如下的代码:

class FinalClass {    public:        static FinalClass* GetInstance() {            return new FinalClass();        }        static void DelInstance(FinalClass* pInstance) {            delete pInstance;            pInstance = NULL;        }    private:        FinalClass() { }        ~FinalClass() { }};

这个类是不能被继承,但是有如下缺点:

1. 需要一个static public member function来创建一个实例

2. 类如果有多个构造函数,所有的构造函数都需要有一个相应的 static-public-member function

3. 类实例对象只能创建在堆上,不能在栈上

 

新奇解法:

class Final; // Forward declarationclass FinalLocker {    public:        friend class Final;    private:        FinalLocker();        ~FinalLocker();};class Final : public virtual FinalLocker {    public:        Final();        ~Final();};

 

Final objFinal;    //OK - no problemDerived objDer;   // Error! - Cant access FinalLocker‘s c‘tor

 

FinalLocker类将其所有ctor和dtor设为private

Final被设为为FinalLocker的friend,这样Final就可以访问 FinalLocker的所有member function,包括private的

Final虚继承FinalLocker,而FinalLocker的ctor和dtor都是private的,我们仍然可以创建Final的实例,堆上栈上都可以,因为Final是FinalLocker的friend

当Derived试图继承Final时,Derived的构造函数必须调用 FinalLocker的构造函数,而FinalLocker的构造函数是private的,所有编译器出错

这是因为 Derived不是FinalLocker的friend,记住 friend关系不是顺沿继承的,Final是 FinalLcker的friend,Derived不一定是,除非显式声明

 

相关资料:

http://prashanth-cpp.blogspot.com/2007/01/implementing-final-class-in-c.html

http://www.stroustrup.com/bs_faq2.html#no-derivation

 

扩展:c++11新添了 final 和 override关键字

final关键字有两个作用:

1. 禁止一个类被继承

class Base final {    ...};class Derived : public Base {    // error,不能从final类继承    ...};

 

 

2. 禁止虚函数被重定义,仅限于虚函数

class Base  {    virtual void func() final;};class Derived : public Base {    virtual void func();    // error,不能重定义基类的final虚函数};