C++设计类不能被继承的方法实例讲解

 更新时间:2013年12月03日 15:21:23   作者:  
在Java 中定义了关键字final,被final修饰的类不能被继承,C++中如何实现,下面我们来看一个例子

首先想到的是在C++中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。

可是这个类的构造函数和析构函数都是私有函数了,怎样才能得到该类的实例呢?可以通过定义静态来创建和释放类的实例。基于这个思路,可以写出如下的代码:

复制代码 代码如下:

///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public :
      static FinalClass1* GetInstance()
      {
            return new FinalClass1;
      }

      static void DeleteInstance( FinalClass1* pInstance)
      {
            delete pInstance;
            pInstance = 0;
      }

private :
      FinalClass1() {}
      ~FinalClass1() {}
};

这个类是不能被继承,但在总觉得它和一般的类有些不一样,使用起来也有点不方便。比如,只能得到位于堆上的实例,而得不到位于栈上实例。

能不能实现一个和一般类除了不能被继承之外其他用法都一样的类呢?办法总是有的,不过需要一些技巧。请看如下代码:

复制代码 代码如下:

///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
template <typename T>
class MakeFinal
{
      friend T;

private :
      MakeFinal() {}
      ~MakeFinal() {}
};

class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public :
      FinalClass2() {}
      ~FinalClass2() {}
};

这个类使用起来和一般的类没有区别,可以在栈上、也可以在堆上创建实例。尽管类MakeFinal<FinalClass2>的构造函数和析构函数都是私有的,但由于类FinalClass2是它的友元函数,因此在FinalClass2中调用MakeFinal<FinalClass2>的构造函数和析构函数都不会造成编译错误。

但当试图从FinalClass2继承一个类并创建它的实例时,却不同通过编译。

复制代码 代码如下:

class Try : public FinalClass2
{
public :
      Try() {}
      ~Try() {}
};

Try temp;

由于类FinalClass2是从类MakeFinal<FinalClass2>虚继承过来的,在调用Try的构造函数的时候,会直接跳过FinalClass2而直接调用MakeFinal<FinalClass2>的构造函数。非常遗憾的是,Try不是MakeFinal<FinalClass2>的友元,因此不能调用其私有的构造函数。

基于上面的分析,试图从FinalClass2继承的类,一旦实例化,都会导致编译错误,因此是FinalClass2不能被继承。这就满足了设计要求。

C++11中已经有了final关键字:它的作用是指定类的虚函数不能被该类的继承类重写(override),或者是指定一个类成为一个不能被继承的类(final class)。

复制代码 代码如下:

struct A
{
    virtual void foo() final;
};

struct B final : A
{
    void foo(); // Error: foo cannot be overridden as it's final in A
};

struct C : B // Error: B is final
{
};

相关文章

  • C语言小程序 数组操作示例代码

    C语言小程序 数组操作示例代码

    对数组进行操作,查找、插入、删除
    2013-07-07
  • C++详细讲解引用类型

    C++详细讲解引用类型

    引用指的是对一个对象的引用。那么什么是对象?在c++中狭义的对象指的是用类,结构,联合等复杂数据类型来声明的变量,如 MyClass myclass,CDialog mydlg,等等
    2022-07-07
  • 基于C语言航班信息查询与检索

    基于C语言航班信息查询与检索

    这篇文章主要为大家详细介绍了基于C语言航班信息查询与检索,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C++&&Opencv实现控制台字符动画的方法

    C++&&Opencv实现控制台字符动画的方法

    这篇文章主要介绍了C++&&Opencv实现控制台字符动画的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • C语言实现猜数字小游戏的示例代码

    C语言实现猜数字小游戏的示例代码

    猜数字小游戏是我们小时候喜欢我们一个经典小游戏。本文将用C语言实现这一经典游戏,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • C++ 和 C# 中的 lambda的方法技巧

    C++ 和 C# 中的 lambda的方法技巧

    这篇文章主要介绍了C++ 和 C# 中的 lambda的方法技巧,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2022-06-06
  • C语言实现学生成绩管理系统

    C语言实现学生成绩管理系统

    这篇文章主要为大家详细介绍了C语言实现学生成绩管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • c++ map索引不存在的key可能导致的后果分析

    c++ map索引不存在的key可能导致的后果分析

    这篇文章主要介绍了c++ map索引不存在的key可能导致的后果分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 通过代码实例解析c++ vector常用方法

    通过代码实例解析c++ vector常用方法

    这篇文章主要介绍了通过代码实例解析c++ vector常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 基于C++实现职工管理系统

    基于C++实现职工管理系统

    这篇文章主要为大家详细介绍了基于C++实现职工管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06

最新评论