- 1、本文档共31页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
类继承和虚函数
类继承和虚函数
第9章 类继承与虚函数
在本章,我们将研究面向对象编程的核心主题—— 类继承。简单地说,继承是一种手段,我们利用继承机制就可以根据现有类定义新类。这一点对C++编程而言非常重要,因此理解继承的工作原理自然也很重要。
在本章,我们将学习以下内容:
● 继承如何和面向对象的编程思想相适应
● 根据现有类定义新类
● 使用protected关键字为类成员指定新的访问特性
● 如何使某个类成为另一个类的友元
● 虚函数及其使用方法
● 纯虚函数
● 抽象类
● 虚析构函数的概念,何时使用虚析构函数
9.1 面向对象编程的基本思想
正如已经看到的那样,类是我们为适应特定应用程序的需求而定义的数据类型。面向对象编程中的类同时定义了和程序相关的对象。我们的程序根据某个问题所特有的对象,使用可以直接处理这些对象的操作,从而成为该问题的解决方案。我们可以定义一个类来表示某种抽象的事物,比如数学概念复数,或者卡车。因此,除了是数据类型之外,类还可以是现实世界中特定种类的一组对象的定义,至少可以说是解决特定问题所需要的定义。
我们可以认为类定义了一组特定事物的特性,这些事物用一组公共的参数来表示,并且共用一组公共的、可以对它们进行处理的操作。可以应用于特定类对象的操作由类接口定义,它们对应于类定义的public部分包含的函数。我们在上一章使用过的CBox类是个很好的例子,它以箱子的尺寸与一组公有函数来定义箱子,这些函数可以应用于CBox对象以解决某个问题。
当然,现实世界中有许多不同种类的箱子:纸板箱、糖果盒与储粮箱。说出来的只是很少几个,我们肯定还能想到好多。可以按照容纳的物品、材质或许多其他方式来区分这些箱子。虽然箱子的种类有许许多多,但它们都有某些共同的特性—— 比如都是四方形的。因此,虽然有许多不同特征,但我们仍然可以将所有种类的箱子视为实际上来源相同。我们可以将某种箱子定义成具有所有箱子的一般特性—— 可能只是长、宽与高,然后可以给基本的箱子类型添加一些其他特性,从而将特定种类的箱子同其他箱子区别开来。我们还可能发现一些可以对特定种类的箱子执行、但不能对其他箱子执行的操作。
有些对象可能是特定种类的箱子和其他类型的对象合并得到的结果,比如糖果盒或啤酒箱。为适应这种情况,我们可以定义一种一般的、具有四方形特性的箱子,然后定义另一种更加特殊化的箱子。图9-1举例说明了被定义的不同种类箱子之间的关系。
图 9-1
当在图中向下移动时,箱子变得更加特殊化,箭头从特定的箱子类型指向这种箱子的父类。图9-1基于一般类型CBox,定义了3种不同的箱子,还定义了啤酒箱作为对容纳瓶子的板条箱的进一步细化。
因此,使用C++类相对准确地模拟现实世界的好方法,就是通过继承来定义相互关联的类。我们可以将糖果盒视为具备所有基本箱子的特性、再加上少许自有特性的箱子。这句话准确阐明了C++中以某个类为基础定义另一个类时类之间的关系。更特殊化的类具有父类的所有特性,再加上少许区别性的自有特性。让我们看一看继承的实际工作情况。
9.2 类的继承
当我们以一个类为基础定义另一个类时,后者被称为派生类。派生类自动包含用来定义自己的那个类的所有数据成员,还有条件地包含了函数成员。我们说该类继承了基类的数据成员与函数成员。
派生类不继承的基类成员仅有析构函数、构造函数以及任何重载赋值运算符的成员函数。所有其他函数成员,连同基类的所有数据成员,都将被派生类继承。当然,某些基类成员不被继承的原因是派生类总是有自己的构造函数与析构函数。如果基类有赋值运算符,派生类也将提供自己的版本。我们说这些函数不被继承,意思是它们不会作为派生类对象的成员存在。但正如我们即将看到的那样,它们仍然作为某个对象的基类组成部分而存在。
9.2.1 基类的概念
任何用作定义其他类的基础的类都是基类。例如,如果我们直接根据类A定义类B,则A是B的直接基类。在图9-1中,CCrate类是CBeerCrate的直接基类。当根据另一个类CCrate定义某个类时—— 比如说CBeerCrate,我们就说CBeerCrate是从CCrate派生的。因为CCrate本身又是根据CBox类定义的,所以说CBox是CBeerCrate的间接基类。我们即刻就将看到如何在类定义中表示这种关系。图9-2说明了派生类继承基类成员的方式。
图 9-2
仅仅因为成员函数被继承,并不意味着我们不需要在派生类中将它们替换成新版本,必要时我们当然可以这样做。
9.2.2 基类的派生类
让我们返回到在第8章开头看到的那个拥有public数据成员的CBox类:
// Header file Box.h in project Ex9_01
文档评论(0)