第8章 虚函数与多态性.pptVIP

  1. 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第8章 虚函数与多态性

第8章 虚函数与多态性 主要内容 8.1 向上类型转换 替代原则在C++中通过向上类型转换实现,可以将一个公有派生类的对象或地址作为基类对象或地址来处理。 派生类向上转换为基类类型,这在逻辑上是合理的,在物理上也是安全的。 在逻辑上方面,派生类继承基类的公共接口,能够发送给基类对象的消息也能够发送给派生类对象。派生类是特殊的基类类型,派生类对象(或地址)可以作为基类的实例(或地址),替代基类对象(或地址)使用。 在物理方面,基类的成员被派生类继承,在派生类对象中封装着一个无名的基类子对象,派生类对象的存储空间中从首地址开始存放的的这个基类子对象。因此,进行向上类型转换时,通过派生类对象切片,能够提供足够的基类信息,得到基类对象。而使用基类指针(或引用)指向派生类对象时也不会破坏指针(或引用)的指向规则。 面向基类编写程序 使用继承和替代原则对于改善代码的结构意义非凡。相对于各种特殊的派生类而言,基类更加抽象,更具一般性。相对于继承层次中比较稳定的上层类,低层派生类更容易发生变更,比如增加新派生类。面向基类在更高的抽象层次上编写程序,程序代码就不会依赖于特殊类型,更加稳定、健壮,具有更好的可扩展性。 一组employee类/通用payroll()函数 class employee{ void salary(){ } }; class manager : public employee{ public: void salary(){/*经理工资的计算和发放*/} }; class programmer : public employee{ public: void salary(){/*程序员工资的计算和发放*/} }; class parttime : public employee{ public: void salary(){/*兼职人员工资的计算和发放*/} }; void payroll(employee re) {//payroll函数 re.salary(); } 代码中类层次如下图所示 payroll()函数具有很强的适应性 程序中的payroll()是面向基类进行处理的函数,这使得payroll()函数具有很强的适应性,它能够处理任意特定类型的employee对象,包括manager、programmer及parttime。隐含的另一个优点是payroll()码的可扩展性:如果需要对类层次进行修改,比如添加新员工类型tester(测试人员),那么只要将tester作为employee的另一个派生类即可,不用修改payroll()函数,它对新增类型仍然适用。 programmer Ron; manager Harry; parttime Lily; payroll(Harry); //OK, manager转换为employee payroll(Ron);//OK, programmer转换为employee payroll(Lily);//OK, parttime转换为employee tester Albus; payroll(Albus);//OK, tester转换为employee 问题 为了避免对象切片现象,这里没有使用对象的向上类型转换。但是,即使引用或指针的向上类型转换仍然会损失源类型的信息。上面的各种员工实例经过转换会丢失自身的类型信息,编译器只知道re是employee类型的,并不知道re实际引用对象的真正类型。因而payroll函数中通过re调用的总是employee版本的salary(),而无法调用到各个派生类中重新定义的salary()操作。这样的替代显然不满足我们所设想的目标。 8.2 虚函数 向上类型转换会损失类型信息,不能真正实现替代原则。这个问题与C++默认的函数调用绑定方式有关。 8.2.1 函数调用绑定 把函数体和函数调用相联系称为绑定(binding,也译作捆绑或编联)。C++中,默认的函数调用绑定方式是早绑定。早绑定又称为静态绑定,即在程序运行之前,由编译器和连接器实现。 void payroll(employee re) { re.salary(); } 在payroll()函数中,对salary()的调用实施早绑定。编译器只知道re是employee类型的引用,所以将re.salary()的调用和employee类的salary()函数体联系在一起。这段程序在执行时就不可能调用到其他类的salary()函数代码。 晚绑定 解决这个问题的方法是使用晚绑定,将绑定推迟到程序运行时。在程序运行时,可以获知实际接收消息的对象的类型,根据这时的类型信息绑定函数调用。晚绑定又称为动态绑定或运行时绑定,必须有某种机制来确定运行时对象的

文档评论(0)

精品文档 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档