收藏 分享(赏)

第六章 多态性与虚函数.ppt

上传人:fmgc7290 文档编号:10201748 上传时间:2019-10-19 格式:PPT 页数:35 大小:300KB
下载 相关 举报
第六章 多态性与虚函数.ppt_第1页
第1页 / 共35页
第六章 多态性与虚函数.ppt_第2页
第2页 / 共35页
第六章 多态性与虚函数.ppt_第3页
第3页 / 共35页
第六章 多态性与虚函数.ppt_第4页
第4页 / 共35页
第六章 多态性与虚函数.ppt_第5页
第5页 / 共35页
点击查看更多>>
资源描述

1、第六章 多态性与虚函数,本章内容,6.1 多态性的概念6.2 一个典型的例子6.3 虚函数6.4 纯虚函数与抽象类,6.1 多态性的概念,在面向对象方法中这样描述多态性:向不同的对象发送同一个消息,它们接收后会产生不同的行为(即方法)。多态性是指同样的消息被不同的对象接收时导致的不同行为。 消息是指对类的成员函数的调用; 不同的行为是指不同的实现,也就是调用了不同的函数。,多态性的概念,函数的重载、运算符重载都是多态现象。 从系统实现的观点看,多态性分为两类:静态多态和动态多态性。 以前学过的函数重载和运算符重载属于静态多态性,在编译程序时系统就可以确定调用哪个函数,因此静态多态性又称编译时的

2、多态性。静态多态性是通过函数重载实现的。 动态多态性是在程序运行中才能确定操作所针对的对象。它又称运行时的多态性。动态多态性是通过虚函数实现的。,本章研究问题,从一个基类派生出不同的派生类时,各派生类可以使用与基类成员相同的成员名,如果在运行时用相同的成员名调用类的成员,会调用哪个类的成员? 通过继承而产生了相关的不同的派生类,与基类成员同名的成员在各个派生类中有不同的含义。,6.2 典型例题,class Circle public:int r;float Area()return PI*r*r; ; class Cylinder:public Circle public:float Area

3、()return 2*PI*r*h; ; class Ball:public Circle public:float Area()return 4*PI*r*r; ;,静态绑定,绑定:将一个函数调用链接上相应于函数体代码的过程。 静态绑定(static banding):在编译时确定函数所调用的函数体。,base,fun,fun,desend,fun,fun,6.3 虚函数,虚函数的作用 静态关联与动态关联 在什么情况下应当声明虚函数,6.3.1虚函数的作用,在类家族中,不同层次的类可以出现名字相同,参数个数和类型都相同而功能不同的函数. 能否用同一个调用形式,即能调用派生类的函数也能调用基类

4、的同名函数? 虚函数的工作原理是在派生类中定义与基类函数同名的函数,通过基类指针或引用来访问基类或派生类中的同名函数。,派生类与基类的转换,赋值兼容性规则 赋值兼容性规则的含义 在需要基类对象的任何地方都可以使用公有派生类的对象来替代。 实质:公有派生类实际上具备了基类的所有功能,凡是基类能解决的问题,派生类都可以解决。,赋值兼容性规则,1.派生类的对象可以给基类的对象赋值。 如 derived d; / derived类是base类的公有派生类 base b; b=d; 反之不然,即基类对象不能赋值给派生类的对象,即使使用强制类型转换也不行,如 d=b; /error d= (derived

5、) b; /error 原因:基类对象不具有派生类的所有成员.,赋值兼容性规则,2.派生类的对象可以初始化基类引用。 如 derived d; / derived类是base类的公有派生类 base ,赋值兼容性规则,3.派生类的对象的地址可以赋给指向基类的指针。 如 derived d; / derived类是base类的公有派生类 base *p; b=,赋值兼容性规则的作用,赋值兼容性规则的引入,对于基类及其公有派生类的对象,就可以使用相同的函数统一处理,而没有必要为每个类设计单独的功能模块 当函数的形参为基类对象时,实参可以是派生类的对象。 当函数的形参为指向基类对象的指针时,实参可以

6、是派生类对象的地址。 当函数的形参为基类对象的引用时,实参可以是派生类的对象。,赋值兼容性规则的作用,结论: 赋值兼容性规则是多态性的基础。同一个函数可以统一处理具有公有派生关系的基类的对象和派生类对象 例6.2开始时没有使用虚函数,然后再讨论使用虚函数的情况 例6.2 基类与派生类中有同名函数display,class Circle protected:float r; public:float Area()return PI*r*r;void input()cinr;void virtual display()cout“r=“rendl; ;,class Cylinder:public C

7、ircle protected:float h; public:float Area()return 2*PI*r*h;void input1()cinr;cinh;void display()cout“r=“rendl;cout“h=“hendl; ;,int main()Circle c;c.input();Cylinder cy;cy.input1();Circle *pt= ,程序运行结果,原因是指针是指向基类的指针。用虚函数就能顺利地解决这个问题。,虚函数的使用方法,(1)在基类用virtual声明成员函数为虚函数。在派生类中重新定义同名函数,让它具有新的功能。(2)在派生类中重新定

8、义此函数时,要求函数名、函数类型、参数个数和类型与基类的虚函数相同,根据需要重新定义函数体C+规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数自动成为虚函数。(3)定义一个指向基类对象的指针变量,并让它获得同一类族中某个对象的地址。(4)用该指针变量调用虚函数,调用的就是该对象所属类的虚函数。,根据虚函数的要求,程序作一点修改,在Circle类中声明display函数时,在最左边加一个关键字virtual,即virtual void display();把Circle类的display函数声明为虚函数。程序其他部分不变,再编译后运行程序,请看程序运行结果:,现在用同一个指针变量不仅输

9、出了基类对象的数据,而且输出了派生类的所有数据说明调用了cy的display函数。,说明,用同一种调用形式pt-display( ),而且pt是一个基类的指针,可以调用同一类族中不同类的虚函数。这就是多态性,对同一消息,不同对象有不同的响应方式。 原来,基类指针是用来指向基类对象的,如用它指向派生类对象,系统要进行指针类型转换,所以基类指针指向的是派生类对象中的基类部分。虚函数突破了这个限制,在基类指针指向派生类对象后,就能调用派生类的虚函数。,函数重载与虚函数,以前介绍的函数重载处理的是同一层次中的同名函数问题,而虚函数处理的是不同派生层次上的同名函数问题 前者要求函数名相同,但函数的参数或

10、类型不同;后者要求的是不仅函数名相同,而且函数参数和类型也要相同,6.3.2 静态关联与动态关联,函数重载和用对象名调用虚成员函数,在编译时即可确定其调用的虚函数属于哪个类,其过程称为静态关联。 在调用虚函数时没有指定对象名,系统怎样确定关联呢?编译系统把它放在运行阶段处理,在运行阶段确定关联关系。,动态关联,在运行阶段,基类指针变量先指向了某个 类对象,然后通过此指针变量调用该对象中的函数。由于在运行中把虚函数和类对象绑定在一起,此过程称为动态关联,这多态性是动态的多态性。 在运行阶段,指针可以先后指向不同的类对象,从而调用同一类族中不同类的虚函数。,6.3.3 在什么情况下应当声明虚函数,

11、注意只能将类的成员函数声明为虚函数。一个成员函数被声明为虚函数后,在同一类族不能再定义一个与该虚函数相同的非虚函数。 声明虚函数时,主要考虑下面几点 首先看成员函数的类是否会作为基类。然后看在派生类里看它是否会被改变功能,如要改变,一般应该将它声明为虚函数。否则不要将它声明为虚函数。 有时在定义虚函数时,函数体是空的。具体功能留给派生类去添加。,问题,什么是Graphic? 计算一个圆的面积可以,但要计算一个图形的面积? 怎么计算?,纯虚函数,有的类没有或不需要实例,即从不创建对象; 你希望所有派生类都必须重定义自己的虚函数使用纯虚函数,纯虚函数语法,virtual 函数类型 函数名(参数)=

12、0; 注意:纯虚函数可以而且应该没有函数体,因为他从来不被执行 例如:class Graphic public:virtual float Area()=0; ; 纯虚函数是在声明虚函数时被初始化为0的函数。,6.4 抽象类,定义:如果一个类至少有一个纯虚函数,那么该类成为抽象类。 规则: 1、抽象类可以有非纯虚成员; 2、抽象类不能建立对象(可以建立指针); 3、抽象类不能用作参数类型、函数返回类型或显示转换的类型。,例,#include class Graphic public:virtual float Area()=0; ; class Rectangle:public Graphic

13、 public:float Area()return length*width; Private:float length,width; ;,void main() Rectangle * arect=new Rectangle();arect-Draw(); ,以下程序是否有错?输出结果是什么?,#include class Graphic public:virtual void Draw()=0cout“draw a graphic“endl; ; class Rectangle:public Graphic public:void Draw()cout“draw a rectangle now “endl; ;,void main() Graphic g;g.Draw();Rectangle * arect=new Rectangle();arect-Draw();Graphic *p=arect;p-Draw(); ,课后作业,1、图形中有矩形、圆、三角形等,这些图形都具有计算面积的功能。 请用纯虚函数和抽象类的概念来设计他们。,实验八 继承性与派生类,实验目的:1、掌握继承的语法格式;2、掌握派生类的成员访问控制属性; 实验内容:1、调试习题2和4,给出实验结果;,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报