




已阅读5页,还剩40页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
理解C 虚拟与多态机制 机器视觉团队技术交流讲座第02讲 主讲教师杨程 目录 多态性虚函数与动态绑定纯虚函数与抽象类实例讲解习题和课后阅读资料 多态性 多态性的定义 何谓多态性 多态性是指给同样的接口发送同样的消息会导致不同的行为 多态意味着一个对象有着多重特征 可以在特定的情况下 表现不同的状态 从而对应着不同的属性和方法 多态性是面向对象程序设计的重要特征之一 若程序设计语言不支持多态性 不能称为面向对象的语言 C 多态性 C 有哪些多态性机制 函数重载运算符重载虚函数函数重载和运算符重载是编译时体现出来的多态性 虚函数则体现了运行时的多态性 虚函数与动态绑定 示例 乐器类继承体系 类定义Instrument 乐器Wind 管乐器Woodwind 木管乐器Brass 铜管乐器Percussion 打击乐器Stringed 弦乐器 接口说明play 演奏adjust 调整乐器what 显示乐器信息 类型的向上转换 Upcasting 将派生类地址 指针或引用 沿着继承树向上的方向赋给基类指针 赋值兼容原则 Upcasting将对象按传址 byaddress 而非传值 byvalue 方式进行操作 而多态性需通过Upcasting来体现 我们想做什么 提供给用户一个通用的不变的系统使用接口 函数tune 无论类进行了怎样的变动 这个接口都能正常可靠地工作 总能按照我们的期望选出正确的乐器演奏 我们想做什么 我们的要求是合理的 这种要求系统具备动态识别能力的需求 在实际运行的很多软件系统当中都是一项基本要求 这正是要求系统具备多态性 voidtune Instrument Upcasting 先看一个例子 includeusingnamespacestd enumnote middleC Csharp Eflat classInstrument public voidplay note const cout Instrument play endl WindobjectsareInstruments becausetheyhavethesameinterface classWind publicInstrument public Redefineinterfacefunction voidplay note const cout Wind play endl voidtune Instrument 我们定义了Wind对象flute 通过接口tune操作play函数 显然我们希望flute对象能正确地调用Wind类的play函数 运行的结果 includeusingnamespacestd enumnote middleC Csharp Eflat classInstrument public voidplay note const cout Instrument play endl WindobjectsareInstruments becausetheyhavethesameinterface classWind publicInstrument public Redefineinterfacefunction voidplay note const cout Wind play endl voidtune Instrument 程序却调用了基类Instrument的play函数 显然这不是我们希望的结果 问题出在哪儿了呢 改动一下例子 includeusingnamespacestd enumnote middleC Csharp Eflat classInstrument public virtualvoidplay note const cout Instrument play endl WindobjectsareInstruments becausetheyhavethesameinterface classWind publicInstrument public Redefineinterfacefunction voidplay note const cout Wind play endl voidtune Instrument 将基类函数play函数定义成为虚函数 virtualfunction 初见虚函数 虚函数 virtualfunction 的定义virtual返回类型函数名 参数表 classShape private public virtualvoidDraw cout Drawashape endl 派生类中的虚函数 虚函数是类成员函数 classmemberfunction 在派生类 derivedclass 中对虚函数的实现重新定义称之为覆盖 override 虚函数的 身份 在继承之间能被持续传递下去 再次运行 结果 includeusingnamespacestd enumnote middleC Csharp Eflat classInstrument public virtualvoidplay note const cout Instrument play endl WindobjectsareInstruments becausetheyhavethesameinterface classWind publicInstrument public Redefineinterfacefunction voidplay note const cout Wind play endl voidtune Instrument 这次结果是我们希望的结果 我们引入了虚函数机制 导致了这样的结果 神奇的 执行方式 以基类指针运行虚函数 程序就能执行我们所期望的正确的派生类的函数体 虚函数为什么会有这样 神奇的 运行机制呢 通过继承而相关的不同类 他们的对象能够对同一个函数作出不同的响应 这样 神奇的 多态性是怎样实现的呢 静态绑定与动态绑定 绑定 binding 程序自身彼此关联的过程 确定程序中的操作调用与执行该操作的代码间的关系 静态绑定 earlybinding 绑定过程出现在编译阶段 用对象名或者类名来限定要调用的函数 动态绑定 dynamic laterbinding 绑定过程工作在程序运行时执行 在程序运行时才确定将要调用的函数 神奇的 执行方式 动态绑定 C 的虚函数在运行时正是通过动态绑定实现多态机制的 动态绑定是如何实现的呢 动态绑定是通过编译器运用虚函数表VTBL和虚表指针VPTR而实现 在运行时通过动态查询实现对正确函数体的绑定 VTBL 编译器会为声明了虚函数的类建立一个虚函数表 VTBL实际上是一个函数指针数组 每个虚函数占用这个数组的一个入口 slot 一个类只有一个VTBL 不管它有多少个实例 派生类有自己的VTBL 但是派生类的VTBL与基类的VTBL有相同的函数排列顺序 同名的虚函数被放在两个数组的相同位置上 VPTR 在创建类实例的时候 编译器还会在每个实例的内存布局中增加一个VPTR指针 该指针指向本类的VTBL 最后 是动态联编 在调用此类的构造函数时 在类的构造函数中 编译器会隐含执行VPTR与VTBL的关联代码 将VPTR指向对应的VTBL 这就将类与此类的VTBL联系了起来 在调用类的构造函数时 指向基类的指针此时已经变成指向具体的类的this指针 依靠此this指针 进一步得到正确的VPTR 即可得到正确的VTBL 从而实现了多态性 在此时才能真正与函数体进行连接 这就是动态联编 一个更大的例子 includeusingnamespacestd enumnote middleC Csharp Cflat Etc classInstrument public virtualvoidplay note const cout Instrument play endl virtualchar what const return Instrument virtualvoidadjust int classWind publicInstrument public voidplay note const cout Wind play endl char what const return Wind voidadjust int classPercussion publicInstrument public voidplay note const cout Percussion play endl char what const return Percussion voidadjust int classStringed publicInstrument public voidplay note const cout Stringed play endl char what const return Stringed voidadjust int 一个更大的例子 classBrass publicWind public voidplay note const cout Brass play endl char what const return Brass classWoodwind publicWind public voidplay note const cout Woodwind play endl char what const return Woodwind voidtune Instrument 一个更大的例子 intmain Windflute Percussiondrum Stringedviolin Brassflugelhorn Woodwindrecorder tune flute tune drum tune violin tune flugelhorn tune recorder f flugelhorn f flugelhorn 函数调用的是哪个版本的adjust 函数呢 虚函数的特点 实现动态多态性时 必须使用基类类型的指针 pointer 或引用 reference 型变量 通过该变量引用虚函数 才能实现动态的多态性 只有类的成员函数才能说明为虚函数 这是因为虚函数仅适用于有继承关系的类对象 静态 static 成员函数 为所有同一类对象共有 不受限于某个对象 不能作为虚函数 虚函数的特点 派生类中定义虚函数必须与基类中的虚函数同名外 还必须同参数表 同返回类型 否则被认为是重载 overload 而不是虚函数 如果定义放在类外 virtual只能加在函数声明前面 不能 再 加在函数定义前面 虚函数的特点 析构函数可定义为虚函数 构造函数不能定义虚函数 因为在构造函数时对象还没有完成实例化 在基类中及其派生类中都动态分配的内存空间时 必须把析构函数定义为虚函数 实现撤消对象时的多态性 采用了虚函数函数执行速度要稍慢一些 为了实现多态性 每一个派生类中均要保存相应虚函数的入口地址表 函数的调用机制也是间接实现 所以多态性总是要付出一定代价 但通用性是一个更高的目标 纯虚函数与抽象类 纯虚函数 purevitualfunction 纯虚函数是指被标明为不具体实现的虚拟成员函数 它用于这样的情况 定义一个基类时 会遇到无法定义基类中虚函数的具体实现 其实现依赖于不同的派生类 定义纯虚函数的一般格式为 virtual返回类型函数名 参数表 0 定义纯虚函数须注意 定义纯虚函数时 不能定义虚函数的实现部分 即使是函数体为空也不可以 函数体为空就可以执行 只是什么也不做就返回 而纯虚函数不能调用 在派生类中必须有重新定义的纯虚函数的函数体 这样的派生类才能用来定义对象 抽象类 abstractclass 的定义 含有纯虚函数的基类是不能用来定义对象的 纯虚函数没有实现部分 不能产生对象 所以含有纯虚函数的类是抽象类 引入抽象类有何意义 1基类的操作表达一种抽象的行为概念 而非能具体化的实体 不必也不能将基类对象实例化 因此使基类成为抽象类 让它表达一种表征共性的概念 而由派生类具体实现纯虚函数表达的概念 2抽象类的纯虚函数表达了一种 规约 和 协议 的含义 只有接口的约定 没有实现的约束 这样就使接口与实现完成解耦 便于软件统一接口的同时保持实现的灵活性 这也正是组件编程的基本思想 抽象类的使用要求 抽象类不能实例化抽象类只作为基类被继承可以定义指向抽象类的指针或引用 实例讲解 includeusingnamespacestd classB0 抽象基类B0声明 public 外部接口virtualvoiddisplay 0 纯虚函数成员 classB1 publicB0 公有派生 public voiddisplay cout B1 display endl 虚成员函数 classD1 publicB1 公有派生 public voiddisplay cout D1 display endl 虚成员函数 例 使用虚函数的例子 voidfun B0 ptr 普通函数 ptr display intmain 主函数 B0 p 声明抽象基类指针B1b1 声明派生类对象D1d1 声明派生类对象p 调用派生类D1函数成员 运行结果 B1 display D1 display 延伸阅读
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电商直播行业主播与品牌合作模式创新趋势及风险控制策略研究报告
- 八年级期中考试家长会课件
- 保育员考试题目及答案
- 安全员b证试题及答案
- 安全试题及答案大题
- 安全生产试题及答案2024
- 生物安全培训课件
- 中国发展简史课件
- 中医推拿科培训课件
- 中国南方区课件
- 新产品评审管理办法
- (参考)菲达公司国内电除尘器业绩表
- 游泳池水质检测记录表
- 大学生职业生涯规划与就业指导教案第5讲:兴趣探索
- 门店电表记录表
- 七年级劳技 花卉种植 花卉用途 PPT学习教案
- 隧道换拱专项施工方案
- 国际金融托马斯普格尔复习资料整理
- 基于单片机的报警器与旋转灯设计(共21页)
- 中国农业银行房地产押品价值评估操作模板
- JJG596-2012《电子式交流电能表检定规程》
评论
0/150
提交评论