




已阅读5页,还剩29页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
面向对象程序设计语言C 电子科技大学示范性软件学院 1 第七章虚函数和多态性 现实生活中 经常出现这种情况 面对同样的消息 不同的人 面对同样的消息 产生不同的反应 面向对象语言是解决现实世界问题的 也需要对这种实际情况进行处理 C 程序设计语言使用多态性实现同一个消息 不同接收者采取不同的响应方式的这种现象 顾名思义 多态性是一个事务有多种形态 在面向对象语言中 一般这样描述多态 向不同对象发送同一个消息 不同的对象在接收时会产生不同的行为 即方法 也就是说 每个对象可以用自己的方式去响应共同的消息 2 第七章虚函数和多态性 C 语言的多态性有两种类型 静态多态性和动态多态性 前面学习的函数重载和运算符重载就是静态多态性的具体示例 在程序编译时系统就能够决定调用哪个函数 因此静态多态性又称为编译时的多态性 动态多态性时程序运行过程中才动态的确定操作所针对的对象 它又称为运行时的多态性 动态多态性是通过虚函数实现的 3 第七章虚函数和多态性 7 1虚函数7 1 1静态多态性对于普通成员函数的重载 可表达为下面的方式 1 在同一个类中重载 2 在不同类中重载 3 基类的成员函数在派生类中重载 因此 重载函数的访问是在编译时区分的 这种程序运行之前就能够在多个函数中确定当前访问的函数的方法称为静态多态性 4 第七章虚函数和多态性 7 1虚函数7 1 1静态多态性有以下三种区分方法 据参数的特征加以区分 例如 Show int char 与Show char float 使用 加以区分 例如 Circle Show有别于Point Show根据类对象加以区分ACircle Show 调用Circle Show 5 第七章虚函数和多态性 7 1虚函数7 1 1静态多态性子类可以重载父类的成员 classA public voidfun cout InA endl classB publicA public voidfun cout InB endl 6 第七章虚函数和多态性 7 1虚函数7 1 1静态多态性CCobj Cobj fun 调用C fun Cobj B fun 调用B fun Cobj A fun 调用A fun A 调用A fun 7 第七章虚函数和多态性 7 1虚函数7 1 2基类和派生类的指针与对象的关系 1 可以用一个指向基类的指针指向其公有派生类的对象 这时 基类指针访问的是派生对象的拥有的基类部分 派生类自身的部分不能被基类指针访问 但是用指向派生类的指针指向一个基类的对象是不正确的 因为派生类指针可以访问派生类公有成员 但基类对象没有派生类自身成员 因此用派生类指针指向基类对象时 如果访问派生类公有成员 而该成员实际不存在 所以不能用指向派生类的指针指向一个基类的对象 2 希望用基类指针访问其公有派生类的特定成员 必须将基类指针用显示类型转换为派生类指针 8 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性1 虚函数的概念一个指向基类的指针可用来指向从基类公有派生的任何对象 这一事实是非常重要的 是C 实现运行时多态性的关键途径 如果有多个或者多层派生类 通过一个基类指针可以访问所有派生类对象的成员函数 这样就可以实现一个接口 多个实现的访问了 但是观察例7 3 基类指针能否访问不同派生类对象的成员函数呢 9 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性classBase public Base inta x a voidwho cout base x n protected intx 10 classFirst d publicBase public First d inta Base a voidwho cout Firstderivation x n classSecond d publicBase public Second d inta Base a voidwho cout Secondderivation x n 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性Base p Basebase obj 1 First dfirst obj 2 Second dsecond obj 3 p 请问程序的输出是什么 11 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性程序的输出是 base1base2base3很奇怪 是吗 明明是指向子类的指针 为什么调用的却是父类的函数版本呢 12 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性答案很简单 因为通过父类指针来看 该指针所指向的是一个父类对象 13 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性如果随着p所指向的对象的不同p who 能调用不同类中who 的版本 这样就可以用一个界面p who 访问多个实现版本 这在编程时非常有用 实际上 这表达了一种动态的性质 函数调用p who 依赖于运行时p所指向的对象 虚函数提供的就是这种解释机制 虚函数是在基类中被冠以virtual的成员函数 它提供了一种接口界面 14 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性虚函数可以在一个或多个派生类中被重新定义 但要求在派生类中重新定义时 虚函数的函数原型 包括返回类型 函数名 参数个数 参数类型的顺序 必须完全相同 前面的程序修改为下页所示就能达到目的 15 第七章虚函数和多态性 7 1虚函数7 1 3虚函数与多态性classBase public Base inta x a virtualvoidwho cout base x n protected intx 16 classFirst d publicBase public First d inta Base a voidwho cout Firstderivation x n classSecond d publicBase public Second d inta Base a voidwho cout Secondderivation x n 例7 4 第七章虚函数和多态性 7 1虚函数2 运行时的多态性与虚特性 1 运行时的多态性晚期匹配如何发生 所有的工作都由编译器在幕后完成 当我们告诉它去晚期匹配 用创建虚函数告诉它 编译器安装必要的晚期匹配机制 关键字virtual告诉编译器它不应当完成早期匹配 相反 它应当自动安装实现晚期匹配所必须的所有机制 那么 编译器会怎么做呢 请先看一个例子 17 第七章虚函数和多态性 7 1虚函数classNoVirtual inti public voidf 18 classOneVirtual inti public voidf virtualvoidg classTwoVirtual inti public voidf virtualvoidg virtualvoidh 第七章虚函数和多态性 7 1虚函数intmain cout sizeofint sizeof int endl cout sizeofpointer sizeof void endl cout sizeofNoVirtual sizeof NoVirtual endl cout sizeofOneVirtual sizeof OneVirtual endl cout sizeofTwoVirtual sizeof TwoVirtual endl return0 19 第七章虚函数和多态性 7 1虚函数假设这个程序的编译环境和运行环境都是32位的 那么请问程序的输出是什么 20 程序的输出如下 sizeofint 4sizeofpointer 4sizeofNoVirtual 4sizeofOneVirtual 8sizeofTwoVirtual 8很奇怪 是吗 拥有虚函数的类尺寸多了4个字节 第七章虚函数和多态性 7 1虚函数很明显 这是4个字节是编译器插入到类中的 那么它是什么呢 在每个带有虚函数的类中 编译器秘密地置一指针 称为虚指针vpointer 缩写为VPTR 此外 编译器对每个包含虚函数的类创建一个虚表 称为VTABLE 在VTABLE中 编译器放置特定类的虚函数地址 VPTR指向这个对象的VTABLE 通过基类指针做虚函数调用时 也就是做多态调用时 编译器取得这个VPTR 找到该类的VTABLE 并在其中查找相应虚函数地址 这样就能调用正确的函数 使晚捆绑发生 21 第七章虚函数和多态性 7 1虚函数 22 第七章虚函数和多态性 7 1虚函数一个成员函数什么时候需要声明为虚函数呢 主要考虑以下几点 首先考虑成员函数所在的类是否会做为基类 然后看成员函数在类的继承后有无功能被修改 如果希望修改其功能 一般将它声明为虚函数 还应当考虑对成员函数的调用是通过对象名还是基类指针或引用去访问 如果通过基类指针或引用去访问 则声明为虚函数 如果希望通过基类指针或者引用访问派生类成员函数 但基类功能比较抽象或者不能确定功能 可以将基类定义为抽象类 即只定义函数名字 没有函数体 具体功能由派生类添加 23 第七章虚函数和多态性 7 1虚函数 2 虚特性用虚函数实现运行时多态性的关键之处是 必须用指向基类的指针 或者引用 访问虚函数 尽管可以像调用其他成员函数那样显式地用对象名来调用一个虚函数 但只有在一个指向基类的指针 或者引用 访问虚函数时 运行时多态性才能实现 这时 称为函数具有虚特性 24 第七章虚函数和多态性 7 1虚函数基类函数具有虚特性的条件是 在基类中 将该函数说明为虚 virtual 函数 这样可以在派生类中重新定义此函数 为它赋予新的功能 并能够方便调用 在类外定义虚函数时 不必再加virtual关键字 定义基类的公有派生类 在基类的公有派生类中原型一致地重载该虚函数 定义指向基类的指针变量 它指向基类的公有派生类的对象 或定义基类的引用 它引用基类的公有派生类的对象 25 第七章虚函数和多态性 7 1虚函数重载一个虚函数时 要求函数名 返回类型 参量个数 参数类型和顺序是完全相同的 如果不同 会产生什么情况呢 1 仅仅返回类型不同 其余相同 C 认为这是错误的 因为仅仅返回类型不同的函数本质上是含糊的 2 函数原型不同 仅函数名相同 C 认为这是一般的函数重载 此时虚特性丢失 例7 5 26 第七章虚函数和多态性 7 1虚函数定义虚函数时需要注意 1 虚函数必须是类的成员函数 不能将虚函数说明为全局 非成员的 函数 也不能说明为静态成员函数 不能将友元说明为虚函数 但虚函数可以是另一个类的友元 2 析构函数可以是虚函数 但构造函数不能为虚函数 3 一旦一个函数被说明为虚函数 不管经历了多少派生类层 都将保持其虚特性 27 第七章虚函数和多态性 7 1虚函数3 虚析构函数请看这个例子 classbase public base cout base endl base cout base endl classderived publicbase public derived cout derived endl derived cout derived endl 28 intmain base pb newderived deletepb return0 第七章虚函数和多态性 7 1虚函数请问程序的输出是什么 29 程序的输出如下 base derived base 构造函数base 和derived 都被调用了 但是析构函数只有 base 调用了 第七章虚函数和多态性 7 1虚函数原因很简单 基类指针只调用基类成员函数 不能够调用派生类成员函数 即使是析构函数也是如此 如果希望能够执行派生类的析构函数 则需要将基类的析构函数声明为虚析构函数 virtual base cout base endl 当基类的析构函数声明为虚函数时 无论指针指向的是同一类族中的哪一个对象 当对象撤销时 系统会采用动态关联 调用相应的析构函数 对该对象进行清理工作 30 第七章虚函数和多态性 7 2纯虚函数和抽象类基类往往表示一些抽象的概念 例如 shape是一个基类 它表示具有形状的东西 从shape可以派生出封闭图形和非封闭图形两个派生类 封闭图形又可以派生出椭圆形 多边形 这个类等级的基类shape体现了一个抽象的概念 在shape中定义一个求面积的函数显然是无意义的 但可以将其说明为虚函数 提供各派生类一个公共的界面 并由各派生类提供求面积函数的各自版本 31 第七章虚函数和多态性 7 2纯虚函数和抽象类在这类情况下 基类的有些虚函数没有定义是很正常的 但是要求派生类必须重定义这些虚函数 以使派生类有意义 为此 C 引入了纯虚函数的概念 纯虚函数是一个在基类中说明的虚函数 它在该基类中没有定义 要求任何派生类都必须定义自己的版本 为说明一纯虚函数 使用下列一般形式 virtualtypefunc name 参数表 0 这里 type是函数的返回类型 func name是函数名 32 第七章虚函数和多态性 7 2纯虚函数和抽象类将一虚函数说明成纯虚函数 就要求任何
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 反假币理论知识培训课件
- 观察日记两则800字15篇
- 企业固定资产盘点清单
- 团队协作计划书模板全面指导
- 厨房安全知识培训课件
- 奔驰汽车安全知识培训课件
- 2025医疗机构批量采购医疗器械买卖合同书
- 卷面书写课件
- 化工企业环境安全培训课件
- 大闹天宫课件
- 2025年彩票市场监察笔试备考手册
- 培训学校租房合同协议书
- 第8课 西溪湿地教学设计-2025-2026学年小学地方、校本课程浙教版(2021)人·自然·社会
- 江淮十校2026届高三第一次联考物理试卷(含答案解析)
- 网络货运行业知识培训课件
- 《从“浪浪山”启程做更好的“小妖怪”!》开学第一课班会教案
- 1.8《天气的影响》教学设计-教科版三上科学(新教材)
- 防地震教学课件
- 消防系统信号传输方案
- T-WHCIA 1008-2025 城市道路软弱土地基处理技术规程
- 2025年7月广东深圳市光明区审计局招聘专干1人笔试参考题库附答案解析
评论
0/150
提交评论