




已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章继承与多态性 本章将介绍面向对象编程中两个非常重要的概念 继承和多态 继承是C 语言中类机制的一部分 该机制使类与类之间可以建立一种上下级关系 继承是一种手段 利用继承机制 可以根据另一个类的操作和数据成员来创建新类 多态性是在继承的基础上实现 它可以实现一个方法有不同的操作 类的继承层次关系派生类对象的结构派生类的访问控制派生类的构造 析构和复制函数相关类类型之间的转换多态性虚函数和抽象类C CLI装箱与拆箱在C CLI中的继承机制C CLI接口类C CLI中的委托和事件 10 1继承的基本概念 类是C 中提供封装的逻辑单位 它封装了变量和函数 同时 C 还提供了继承机制 通过继承 过去的代码就不需要丢弃 只需要经过稍加修改后就重用 在人类文明的发展中 现在的文明就是建立其先人文明的基础上 事实上 事物的发展都是从建立其先前的基础上的 类的继承就反映了从先前简单代码发展到丰富的高级代码的过程 10 1 1类的层次关系 利用继承性 可以在已有类的基础上构造新类 这一性质使得类与类之间可以建立一种上下级的分类关系 继承关系使得我们可以用一种简单的方式来描述事物 例如 描述什么是鹰 可以描述为一种大型的食肉鸟类 鹰是一种鸟 所以鹰是鸟类的派生 但鹰又具有自己的特征 大型的以食肉为主的特征是它区别于其他鸟类的属性 由于鸟类通常的特征大家都知道 如 有翅膀 有两个脚等 所以用鸟类来描述鹰 只要列举出它自己的所具有特点即可 描述事物一般是从属性和操作上来描述的 例如 日期具有年 月 日的属性 显示日期 判断某年是否为闰年的操作 继承就是让子类继承父类的属性和操作 子类可以声明新的属性和操作 还可以替换哪些不适合其用途的父类操作 在新的应用中 父类的代码已经存在 无须修改 所要做的就是派生子类类 并在子类中添加和修改 所以继承可以重用父类的代码 提高代码的利用率 继承也是我们理解事物 解决问题的方法 继承帮助我们描述事物的层次关系 有效而精确地描述事物 理解事物直至本质 一旦看清了事物所处的层次关系 也就可以找到相关的解决办法 10 1 2派生类对象的结构 如果类BaseClass是父类 classBaseClass private inta b 私有成员public 公有成员 该类对象包含了两个整型数据成员所占用的内存空间 在该父类上派生子类的方式是在子类名后添加public关键字和父类名 如SubClass继承的BaseClass类 则 classSubClass publicBaseClass private intc 私有成员public 公有成员 子类SubClass的对象包含两部分 一部分为父类部分 即两个整型数据成员所占用的 空间 另一部分为子类新添加的整数空间 10 2继承机制下的访问控制 在继承机制下 类的访问控制符又有了新的意义 例如 对于父类的私有成员 在子类中是否可以直接访问 本节将对介绍父类中的访问控制对子类的影响 访问父类成员继承方式 10 2 1访问父类成员 如果将基类中的数据成员变为私有的private 则上面的程序将无法编译 并提示无法访问Person类的private成员 也就是说 子类不能访问基类的private成员 原因在于虽然基类的private成员也中派生类的成员 但它们在派生类中仍然为基类所私有的 因此在派生类中不能访问基类的private成员 如果需要在派生类中访问基类的private成员 只能通过访问基类的public成员实现 10 2 2继承方式 继承可以是公有继承 也可以是保护继承和私有继承 多数情况下 类的继承是公有的 就像前面所看到的 也就是在子类名后使用public访问控制符限定基类名 如果将子类名和基类名之间的public关键字替换为private或protected 则继承就变为私有继承和保护继承 公有继承反映了派生类对基类使用的方式全部接受 在此基础之上进行扩充 以便能被外界更广泛地使用 因此 通过派生类对象仍然可以使用基类中原来公有的操作 派生类不能获取基类私有成员的访问权限 除此之外 公有继承将基类的保护成员或公有成员视为自己的保护和公有成员 10 3派生类的构造函数 类的构造函数作为类的一种特殊成员函数 它们不会被派生类继承 仍然存在于基类中 并且用于创建派生类对象中基类对象部分 因为创建派生类对象的基类部分实际上属于基类构造函数 而非派生类构造函数的任务 如前面 基类的私有成员在派生类中虽然会被继承 但是不可访问 因此这些任务必须交给基类的构造函数来完成 根据类机制 如果没有定义构造函数 将会执行默认的无参构造函数 对于派生类而言 派生类的默认无参数构造函数会首先调用父类的默认无参构造函数 如果在基类中提供了有参数的构造函数 并且没有重载默认的构造函数 则派生类的默认构造函数将无法正常工作 为了解决这个问题 可以自定义派生类的构造函数 并在派生类的构造函数中调用基类的构造函数 10 4派生类的析构函数 在派生类对象超出作用域时 或者要删除堆内存中的对象时 总是要涉及到派生类的析构函数和基类的析构函数 与构造函数一样 析构函数也不能被继承 在派生类中需要自行声明 下面为Person类和Employee添加析构函数 并跟踪何时调用这两个析构函数 Person Person cout Person析构函数 endl Employee Employee cout Employee析构函数姓名 GetName endl 10 5派生类的复制构造函数 复制构造函数是使用一个已有对象创建同类对象时被自动调用 如下面的两条语句 PersonaPerson 刘丽 1979 10 23 PersoncopyPerson aPerson 第一条语句调用构造函数创建Person类对象 第二条语句则调用复制构造函数创建Person类对象 如果不提供自定义的复制构造函数 则编译器会自动提供一个默认的复制构造函数 将初始化对象成员逐一复制到新对象对应的成员中 为了解复制构造函数的工作过程 可以给Person类添加自动定义的复制构造函数 然后为派生类Employee添加自定义构造函数 10 6多重继承 在有些时候 我们还需要多重继承 即一个派生类有两个以上的直接基类 例如 人类都不是单亲繁殖的 一个人总是从他母亲和父亲两个方面继承 多重继承的使用并不多见 在Java C 等编程语言甚至没有多重继承 因此这里也不深入介析 只是简单说明多重继承基本工作源理 多重继承涉及到到用两个或多个直接基类来派生一个新类 它要比单一继承要复杂的多 多重继承意味着将多个基类的特性加在一起 形成一个包含所有基类功能的合成对象 这通常比较便于实现 而不便于反映对象之间的关系 10 7在相关的类类型之间转换 每个派生类对象都至少包含一个基类对象 把派生类型转换为基类类型是合法的 在类层次结构中 向上的转换是合法的 反之 向下的转换则是不合理的 也就是说 只能用子类对象向其基类对象赋值 而不能用基类对象向其派生类对象赋值 因为基类对象不包含派生类的成员 无法对派生类的成员赋值 同样 同一基类的不同子类之间也不能赋值 10 6理解多态性 多态性是面向对象程序设计的重要特征之一 它与前面介绍的封装性 继承构成了面向对象程序设计的三大特征 这三个特征是相互关联的 封装性是基础 继承是关键 多态性是补充 而多态是通过继承来实现的 所谓多态性是指同样的消息被不同类型的对象接收时 各类型的对象会采用完全不同的行为 这里所说的消息主要是指对类成员的调用 也就是说 不同功能的函数可以使用同一个函数名 这样就可以用一个函数调用不同内容的函数 从系统实现的角度看 多态性分为两类 静态多态性和动态多态性 10 6 1虚函数 虚函数的作用是允许在派生类中重新定义与基类同名的函数 并且可以通过基类指针或引用来访问基类和派生类中的同名函数 在C 中规定 当一个成员函数被声明为虚函数后 其派生类中的同名函数都自动成为虚函数 因此 在声明派生类的虚函数时 可以添加virtual关键字 也可以不添加 如果在派生类中没有对基类的虚函数重新定义 则派生类将直接继承基类中的虚函数 虚函数实现的动态多态性是一个极为强在的机制 在交互式应用程序中 常常不能事先确定要处理哪种类型的对象 即在设计或编译期间不能确定类型 只能在运行期间确定 10 6 2使用虚函数的原则 使用虚函数时应注意几点 1 函数的签名和返回类型在派生类和基类中声明 定义虚函数时 函数的名称和参数列表必须相同 一般情况下 在派生类中的返回类型也必须与基类相同 但当基类中的返回类型是类类型的指针或引用时例外 2 虚函数和类层结构虚函数的作用是允许在派生类中对基类的虚函数重新定义 它只能用于类的继承层次结构中 在基类中可以声明任意多个虚函数 但在有若干层的类层次结构中 各层的类都可以添加属于自己特有的虚函数 3 访问修饰符与虚函数虚函数在派生类中声明时 所用的访问修饰符可以不同于其在基类中声明时的访问修饰符 在通过指针调用虚函数时 基类中的访问修饰符将确定该函数是否可以在派生类中访问 如果虚函数在基类中声明为public 则无论它在派生类中的访问修饰符是什么 都可以通过基类的指针或引用为所有派生类调用该函数 10 9纯虚函数和抽象类 有时在基类中将某一个成员函数定义为虚函数 并不是该基类本身的需要 而是考虑到派生类的需要 在基类为中预留一个函数名 函数的具体功能由派生类根据需要定义 纯虚函数的主要作用是允许函数的派生类版本进行多态性的调用 要把函数声明为纯虚函数与声明一般虚函数相同 但在类的声明中要添加 0 纯虚函数通常没有实现代码 10 9 1纯虚函数 10 9 2抽象类 抽象类是包含纯虚函数的类 因为纯虚函数是不能被调用的 包含纯虚函数的类是无法建立对象的 抽象类的作用是作为一个类族的共同基类 即为一个类族提供一个公共接口 抽象类可以拥用数据成员和函数成员 判断抽象类的唯一条件是类中是否包含纯虚函数 抽象类中以包含多个纯虚函数 这种情况下 派生的子类必须给出每个纯虚函数的定义 否则该派生类仍然是抽象类 10 10C CLI的应用 在C CLI中 默认情况下用户自定义的类都是派生类 因为数值类和引用类都是以System Object为基类的 这意味着数值类和引用类都继承于System Object类 具有System Object类的功能 System Object类的ToString 函数被定义为虚函数 在自己的类中重写该函数 并在需要时多态地调用该函数 10 10 1装箱与拆箱 基类System Object还负责实现基本类型数值的装箱 boxing 和拆箱 unboxing 操作 装箱就是将一个值类型隐式或显式地转换成一个引用类型 把一个值类型的值装箱 就是创建一个引用类型的实例并将这个值复制给这个引用类对象 装箱后的引用类对象中的数据位于堆中 堆中的地址在栈中 被装箱的类型的值是作为一个拷贝赋给对象的 10 10 2C CLI中的继承 虽然数值类是以System Object为基类 但是不能从现有类中派生数值类 自定义数值类只可以从接口类中派生 这意味着数值类中的多态性仅限于在System Object类中被定义为虚函数的那些函数 当然 System Object也是引用类的基类 所以在引用类中也需要重写这些函数 在C CLI中派生子类的方式与本地C 中相同 可以从现有的引用类派生出新的引用类 下面总结了在C CLI中派生类与ANSIC 派生类的区别 只有引用类可以是派生类 派生引用类的继承方式只能是public 引用类中没有定义的函数是抽象函数 必须使用abstract关键字声明 包括抽象函数的类为抽象类 抽象类需要在类名后添加abstract关键字 不包含抽象函数的类也可以被指定为抽象类 以防止从创建该类的对象 当在派生类中重写基类中的抽象函数时 必须显式使用override关键字表示重写 10 10 3接口类 接口类指定一组将由其他类实现的函数 以提供标准化的 可提供某
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 三、带参数的过程教学设计-2023-2024学年小学信息技术(信息科技)六年级上册电子工业版(宁夏)
- Self-assessment说课稿-2025-2026学年高中英语沪教版2020选择性必修第二册-沪教版2020
- 第11课 三光感走轨迹的机器人说课稿-2025-2026学年初中信息技术川教版九年级下册-川教版2018
- 2025企业采购合同执行情况yMC
- 2025年大连市房屋租赁合同
- 九年级化学下册 第11单元 化学与社会发展 第1节 化学与能源开发说课稿 (新版)鲁教版
- 本册综合说课稿-2025-2026学年高中物理第二册沪科版(2020·上海专用)
- 云南省昆明市黄冈实验学校人教版高中数学必修三:1.2.2 条件语句-教学设计
- 2024秋八年级数学上册 第十一章 三角形11.2 与三角形有关的角 1三角形的内角-三角形的内角和说课稿(新版)新人教版
- 2025年电子产品出口贸易合同范本
- 中医面瘫护理个案汇报
- 《水基路用聚合物稳定碎石基层技术规程》
- 快递柜租赁合同
- 产品研发流程管理指南
- 《车刀与切削原理》课件
- 2024高考物理全国二卷
- 2024-2030年中国猎头公司市场发展前景调研及投资战略分析报告
- 注塑检验员培训
- 消防安全操作员培训合同范本
- 消防控制室操作规程培训
- 国庆节磨豆腐活动方案
评论
0/150
提交评论