电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

c++语言简明教程 教学课件 ppt 作者 吴延海_ 第5章

56页
  • 卖家[上传人]:E****
  • 文档编号:89343103
  • 上传时间:2019-05-23
  • 文档格式:PPT
  • 文档大小:257.50KB
  • / 56 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 1、,第5章 类的多态性,5.1 类的多态 5.2 运行时的多态性 本章小结,多态性是面向对象程序设计的一个重要特征,多态性有很多种,反映出客观世界的多样性,能够提供程序设计的极大灵活性。,多态性的种类很多,运行时的多态性是多态性中重要的一种,C+ 语言用虚函数方法实现运行时的多态性。,5.1 类 的 多 态,5.1.1 多态性的概念 多态性是面向对象程序设计的一个重要特征。“一个函数名,不同的功能”,这是多态性最简单的表述。类的多态性体现在面向对象程序设计的许多方面,函数重载、函数的覆盖继承、虚函数以及类模板均是多态性的体现。,函数重载要求重载的函数在同一名字空间中使用相同的函数名,但必须保证函数的参数个数或者参数类型不同,编译环境利用名字分裂机制在内部区分了各个重载的函数,认为是不同的函数。这样同一个对象调用相同的成员函数时,会由于参数个数不同或参数类型不同而产生不同的调用结果。 前面讲过,在类继承中派生类可以覆盖基类定义过的成员函数,要求派生类中要覆盖的成员函数在其函数名、参数个数和参数类型与基类成员函数完全一样。,否则,系统将按成员函数重载考虑。当派生类覆盖了基类的某个成员函数时,

      2、如果派生类对象调用了覆盖的成员函数时,则系统匹配的方法是自当前派生类层向上逐层匹配,直到匹配到一个成员函数为止。 但是,在程序设计时,仅仅通过派生类是否覆盖基类定义过的成员函数提供的多态性有时不够灵活。比如考虑到赋值兼容准则,一个基类的对象指针可能指向派生类,那么该对象指针调用了覆盖函数的话,系统只是调用基类中的该函数,而并未调用派生类中的函数。,如果对于一个类层次来说,同样一个成员函数的调用,程序中动态确定的对象不同,则调用的成员函数不同。这样多态性能提供程序设计更大的灵活性,此多态性称做运行时的多态性。本章主要讨论这种多态性。 另外,面向对象技术还支持函数参数的多态性,这需要使用模板方法来实现。,5.1.2 多态性的种类 如上节所述,面向对象技术支持的多态性主要包括四种:强制多态、重载多态、包含多态和参数类型多态。 (1) 强制多态是指将一种类型的值转换为另一种类型的值进行的语义操作,从而防止类型错误。类型转换可以是隐式的,在编译时完成;也可以是显式的,可在动态运行时完成。C+ 语言定义了基本数据类型之间的隐式转换规则,即,char-short-int-unsigned-long-

      3、unsigned long-float-double-long double 但在赋值运算中,这一规则并不适用。赋值运算时,是将赋值运算符右边变量的数据类型转换为运算符左边变量的数据类型。前面讲过,C+ 语言可使用两种语法进行强制类型转换: (类型说明符)变量名 或 类型说明符(变量名) 另一种重要的显式类型转换就是构造函数,构造函数进行的类型转换只能将参数类型向类类型转换。如果要把类类型的数据转换成所指定的某种数据类型,就需要使用类型转换函数。,类型转换函数又称为类型强制转换成员函数,它是类中的一个非静态成员函数。它的定义格式如下: class public: operator ( ); ; 这个转换函数定义了由到之间的映射关系。,【例5.1】 类型转换函数范例:将分数类转换为双精度型。 /- /c0501.cpp /- #include class Rational private: int den; /分数的分子,int num; /分数的分母 public: operator double(); /类型强制转换成员函数的声明 Rational(int d, int n) /构造

      4、函数 den=d; num=n; ;,Rational:operator double( ) /类型强制转换成员函数的定义 return double(den)/double(num); /返回double型的分数值 void main() Rational r(5,8); double d=4.7; d+=r; /隐式调用类型强制转换成员函数,coutdendl; 执行该程序输出结果:5.325。 说明: 程序中d是一个double型数据,r是Rational类对象。这两个不同类型的数据的加法之所以能够进行,是得益于类型转换函数operator double( )。当然也可以在程序中使用显式类型强制转换函数,将加法语句改为d+=double(r)。 定义类型转换函数时需要注意的是:类型转换函数不可以有返回值,类型转换函数的名称就是类型转换的目标类型。,类型转换函数也不带任何参数,它用于将本类型的数值或变量转换成其他类型;也不可以将类型转换函数定义为友元函数。 (2) 重载多态是多态性中最简单的形式,它分为函数重载和运算符重载。函数重载允许功能相近的函数使用相同的函数名,编译系统依据这

      5、些函数参数个数或者参数类型不同区别不同的函数。运算符重载是对已有运算符赋予多重含义,同一个运算符作用于不同类型的数据导致不同类型的行为。它的实质是函数重载,重载的是已有的运算符,在下一章中我们将重点介绍。,(3) 包含多态是通过虚函数来实现的。如果派生类中覆盖了基类对象的函数,根据赋值兼容,用基类类型的指针指向派生类,就可以通过这个指针来使用派生类的成员函数。如果这个函数是普通的成员函数,通过基类类型的指针访问到的只能是基类的同名成员。而如果将它设置为虚函数,则可以使用基类类型的指针访问到指针正在指向的派生类的同名函数。这样,通过基类类型的指针,就可以使属于不同派生类的不同对象产生不同的行为,从而实现运行过程的多态。,(4) 参数多态与类模板相关联,它把功能相似仅数据类型(或类类型)不同的函数或类设计为通用的函数模板或类模板,从而实现了相同的函数或类的成员函数对多种数据类型的数据处理。 C+ 语言中,函数重载和子类对父类成员函数的覆盖继承,实现的都是编译时的多态性,而虚函数实现的是运行时的多态性。所谓编译时的多态性就是指系统在编译时就确定了调用同名函数中的具体哪一个函数,而运行时的多态

      6、性则需要系统在运行期间根据每一个对象指针指向的对象确定调用父类或是子类的成员函数,虚函数标示了采用滞后联编实现运行时的多态性。,C+语言是利用虚函数实现运行时的多态性的。对于存在虚函数的类层次中,系统将按照滞后联编的方式考虑调用对象的成员函数。,5.2 运行时的多态性,5.2.1 滞后联编 联编(binding)就是将一个标示符名和一个内存地址绑定在一起的过程。在这个过程中将对每个函数调用分配内存地址,并且对外部访问也分配地址,这样就将标示符名和存储地址结合在一起。根据联编所处的阶段不同,可以分为两种不同的联编方式:早期联编和滞后联编(也称静态联编和动态联编)。对于同名函数的调用,如果在编译时决定执行哪个同名函数,则称为早期联编,,反之在编译阶段不能决定执行哪个同名的被调用函数,只在执行阶段才能依据要处理的对象的类型来决定执行哪个类的成员函数,这称为滞后联编。一些支持面向对象的程序设计语言(如Java语言)完全使用滞后联编,而C+ 语言兼容C语言,采用了两种联编方式结合的编译方式。C+ 中用虚函数来标示滞后联编,即对于没有标记为虚函数的成员函数调用,系统采用早期联编;对于标示为虚函数的

      7、则采用滞后联编。,由于存在函数重载,以及存在派生类对基类成员函数的继承和覆盖,因此要确定每个对象消息(即成员函数的调用)和类层次中某类的成员函数的匹配。这既可以采用早期联编的方式确定,也可以采用滞后联编的方式确定。早期联编在编译阶段必须了解所有的函数和模块执行所需检测的信息,它对函数的选择是基于指向对象的指针(或引用)的类型。而滞后联编对成员函数的选择不是基于指针或引用,而是基于对象类型,针对不同的对象类型将做出不同的编译结果。,5.2.2 虚函数 C+ 语言中,使用虚函数标示滞后联编,在类的成员函数前加virtual关键字就构成虚函数。声明虚函数的语句格式为 virtual 只有在类层次中才可以声明虚函数,虚函数存在于类继承中,只有一个类中存在虚函数是无意义的。和函数的覆盖继承一样,派生类中虚函数的函数名、参数个数、参数类型以及返回类型必须与基类中声明的虚函数完全一样,并且要求派生类必须公有继承基类。,要使用虚函数时,在外部程序中定义一个指向基类对象的指针。依据赋值兼容准则,该指针也可指向派生类对象。如果该对象指针调用类层次中的虚函数时,若此时该对象指针指向基类对象,则系统就调用基类

      8、中的相应成员函数;若此时基类对象指针指向派生类对象,则系统就调用派生类中的相应成员函数。,【例5.2】 虚函数范例。 /- /c0502.cpp /- #include class A public: /构造函数 A(void),/定义虚函数 virtual void f1(void) const cout“基类的f1( )函数“endl; /定义一般成员函数 void f2(void) const cout“基类的f2( )函数“endl; ;,/使用虚函数时类层次间是公有继承 class AA: public A public: AA(void) / f1为虚函数 void f1(void)const cout“派生类的f1( )函数“endl; ,/f2为成员函数覆盖继承 void f2(void) const cout“派生类的f2( )函数“endl; ; void main(void) ,A *pa, myA; /定义基类指针pa和基类对象myA AA myAA; /定义派生类对象myAA pa= /调用基类的f2()函数,myA.f2(); /调用基类的f2()函数 my

      9、AA.f2(); /调用派生类的f2()函数 程序运行后的结果是: 基类的f1()函数 基类的f2()函数 派生类的f1()函数 基类的f2()函数 基类的f2()函数 派生类的f2()函数,说明: (1) 上面例程中,派生类中f1()函数前未有关键字virtual但仍是虚函数。因为在派生类中声明的某个成员函数在其函数名、参数个数、参数类以及返回类型和基类中声明的虚函数完全一样,那么系统自动视作虚函数。 (2) 从上面的例程可以看出,虚函数标示的滞后联编在运行时依据对象指针当前所指的对象是基类或派生类的,则调用对应的基类或派生类的成员函数。而一般的成员函数的覆盖继承则在编译时就依据对象指针的类型决定了始终调用某一类对象的成员函数。,如例中f2()函数是一般覆盖继承的函数,那么不管基类指针pa当前指向派生类或是基类对象,利用pa调用f2()函数时始终执行的是基类的f2()函数。,5.2.3 虚函数和覆盖继承的区别 虚函数也像派生类对基类成员函数的覆盖那样,在派生类中覆盖了基类的虚函数。但由于系统对虚函数采用滞后联编的编译方式,因此二者是有很大差别的。 对于派生类对基类成员函数的覆盖,调用成员函数的对象或对象指针在程序编译时就已确定,它对函数的选择是基于指向对象的指针(或引用)的类型,即要么是基类对象,要么是派生类对象,只能属于固定的一种,不能在程序运行时改变。,如果某对象或对象指针调用了一个覆盖的成员函数,则编译时系统的匹配方法是自该对象或对象指针定

      《c++语言简明教程 教学课件 ppt 作者 吴延海_ 第5章》由会员E****分享,可在线阅读,更多相关《c++语言简明教程 教学课件 ppt 作者 吴延海_ 第5章》请在金锄头文库上搜索。

      点击阅读更多内容
    最新标签
    信息化课堂中的合作学习结业作业七年级语文 发车时刻表 长途客运 入党志愿书填写模板精品 庆祝建党101周年多体裁诗歌朗诵素材汇编10篇唯一微庆祝 智能家居系统本科论文 心得感悟 雁楠中学 20230513224122 2022 公安主题党日 部编版四年级第三单元综合性学习课件 机关事务中心2022年全面依法治区工作总结及来年工作安排 入党积极分子自我推荐 世界水日ppt 关于构建更高水平的全民健身公共服务体系的意见 空气单元分析 哈里德课件 2022年乡村振兴驻村工作计划 空气教材分析 五年级下册科学教材分析 退役军人事务局季度工作总结 集装箱房合同 2021年财务报表 2022年继续教育公需课 2022年公需课 2022年日历每月一张 名词性从句在写作中的应用 局域网技术与局域网组建 施工网格 薪资体系 运维实施方案 硫酸安全技术 柔韧训练 既有居住建筑节能改造技术规程 建筑工地疫情防控 大型工程技术风险 磷酸二氢钾 2022年小学三年级语文下册教学总结例文 少儿美术-小花 2022年环保倡议书模板六篇 2022年监理辞职报告精选 2022年畅想未来记叙文精品 企业信息化建设与管理课程实验指导书范本 草房子读后感-第1篇 小数乘整数教学PPT课件人教版五年级数学上册 2022年教师个人工作计划范本-工作计划 国学小名士经典诵读电视大赛观后感诵读经典传承美德 医疗质量管理制度 2 2022年小学体育教师学期工作总结
    关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
    手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
    ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.