第六章多态性与虚函数PPT讲稿.ppt
《第六章多态性与虚函数PPT讲稿.ppt》由会员分享,可在线阅读,更多相关《第六章多态性与虚函数PPT讲稿.ppt(80页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第六章多态性与虚函数第1页,共80页,编辑于2022年,星期三封装性和继承性为软件设计提供了可靠的安全性和良好的结构层次。在此基础上,多态性使软件中的对象行为更加符合软件所模拟的客观世界中对象行为的多样性,为软件设计中的功能实现和任务调度提供了灵活性。多态性是指当不同的对象收到相同的消息时产生不同的动作。即调用同一个函数名,可以根据需调用同一个函数名,可以根据需要,实现不同的功能。要,实现不同的功能。C+支持两种多态性:编译时多态性和运行时多态性。本章所叙述的内容是运行时多态性的工作机制和实现方法。第2页,共80页,编辑于2022年,星期三编译时多态性:又称静态多态,是指在编译阶段根指在编译阶
2、段根据函数名和参数确定应该调用哪一个函数,据函数名和参数确定应该调用哪一个函数,其过程称为静态关联或早期关联静态关联或早期关联。运行时多态性:又称为动态多态性,是指在编译阶是指在编译阶段根据函数名和参数无法确定应该调用哪一个函数,段根据函数名和参数无法确定应该调用哪一个函数,必须在程序的执行过程中,必须在程序的执行过程中,根据具体的执行情况来根据具体的执行情况来动态地确定。动态地确定。这种关联称为动态关联或后期关联动态关联或后期关联。实现的途径是:继承和虚函数。只使用编译时多态性机制的程序设计只能称为基于对象(Object Based)的程序设计,使用了运行时多态性机制,才能称为是面向对象(O
3、bject Oriented)的程序设计。第3页,共80页,编辑于2022年,星期三所谓运行多态性是相对与编译多态性而言的。二者的共同作用是实现对象行为的多样性,但在实现方法上和对程序运行控制的作用上有着很大的不同。1 编译多态性的局限性由于编译多态性是通过函数重载实现的,因此对象行为的确定(函数的运行绑定)只能由编译器根据程序源代码的安排在编译过程中实现。这样实现的对象行为多样性虽然具有良好的可读性,但在控制程序运行和对象行为多样性方面存在着局限性:6.1 运行多态性第4页,共80页,编辑于2022年,星期三 对象行为的多样性必须是预先确定可知的,程序运行的控制必须是预先规划固定的,因此只能
4、解决软件所模拟的客观世界中那些可以预先确定和控制的事件的实现。调用重载函数的不同版本(确定对象行为的多样性)是依据参数(个数和类型)的差别实现的(派生类对基类同名、同参数成员函数的覆盖除外),即发送给不同对象的消息并不完全一致。从这一点分析,编译多态性所实现的并非完备意义上的多态性,即不同对象接收到同一函数调用(函数名和参数完全一致),表现出不同的行为。第5页,共80页,编辑于2022年,星期三2 运行多态性要实现的目标运行多态性要实现的目标是在保持编译多态性所能实现的功能的基础上,克服编译多态性的局限性:能根据程序运行中状态的变化,动态确定接收函数调用的对象和对象行为的多样性,使得软件能够实
5、现所模拟的客观世界中那些无法预先确定事件的发生和完成。完全相同的函数调用(函数名和参数完全一致)能够触发(调用)不同类对象的特定行为,从而实现完备意义的多态性,使得复杂的对象行为控制变得更加简单、统一。第6页,共80页,编辑于2022年,星期三3 运行多态性的实现机制使程序具有运行多态性的关键是能否在程序运行期间,根据程序的运行状态,动态地修改程序的运行控制指针。C+(包括C)的编程要素 指针变量为动态多态性提供了基本实现机制,即程序能够在运行期间通过修改指针变量的当前值,动态地确定程序的当前操作和操作所施加的数据(对象)。指针变量分为两种:第7页,共80页,编辑于2022年,星期三 数据指针
6、变量用于动态确定操作数据,即通过指针而不是使用数据变量名访问数据变量。其定义格式为:数据类型*指针变量名;例如:double*pt;数据指针变量的值是数据空间的首地址,赋值合法性依据是首地址所指示数据的类型。例如:double d;int i;pt=&d;/合法pt=&i;/非法第8页,共80页,编辑于2022年,星期三 函数指针变量用于动态确定操作,即通过指针而不是使用函数名实现函数调用。其定义格式为:返回数据类型(*指针变量名)(参数据类型,);例如:int(*fun)(int,int);函数指针变量的值是函数的调用地址,赋值合法性依据是调用地址所指示的函数类型(函数的返回类型,参数个数、
7、类型和顺序)。例如:int max(int,int);void count(double);fun=max;/合法或fun=&max;fun=count;/非法第9页,共80页,编辑于2022年,星期三在面向对象程序设计中操作和操作所施加的数据是绑定和封装在对象中的。因此,实现动态多态性是在程序运行期间,根据运行状态,动态改变接收同一函数调用的对象,由对象的行为确定操作和操作所施加的数据,从而实现动态地修改程序的运行控制指针。响应同一函数要求被调用的对象成员函数原型(函数名,返回类型,参数个数、类型和顺序)一致,显然这是函数重载所不能支持的。函数指针虽然能够支持动态多态性,但在面向对象程序设计
8、中直接使用函数指针既烦琐又违背面向对象的设计原则。因此必须引入新的编程机制 虚函数。6.2 虚函数第10页,共80页,编辑于2022年,星期三通过指针变量动态确定接收同一函数的对象是实现动态多态性的第一步,首要条件。1 一般对象的指针 一般对象的指针与系统预定义数据的指针,在定义和使用语法上都相同;无派生关系的不同类对象指针之间不允许相互转换,如果强制转换,可能会引起不可预期的结果。例如:6.2.1 对象指针第11页,共80页,编辑于2022年,星期三#include class class1 int a,b;public:class1(int x,int y)a=x;b=y;void sho
9、w()cout my_base-n;cout a b endl;第12页,共80页,编辑于2022年,星期三class class2 int c;public:class2(int x)c=x;void show()cout my_class-n;cout c=c show();ptr=&c2;/错误ptr-show();如果将代码ptr=&c2;修改为ptr=(class1*)&c2;则会引起不可预测的执行结果,例如:my_base-50 50my_base-30 6684136第14页,共80页,编辑于2022年,星期三2 具有派生层次的类对象指针由于派生类是由基类继承定义的,即派生类的对
10、象中总是包含着基类对象部分,并在派生类对象的创建过程中首先被创建。因此,基类对象和派生类对象的首地址所指示的对象类型是向后兼容的,即允许基类指针既可以指向基类对象,也可以指向派生类对象。第15页,共80页,编辑于2022年,星期三使用基类指针时要注意以下几个问题:基类指针可以指向该基类的公有派生类对象,但不能自动指向该基类的私有派生类对象(除非使用强制转换实现)。例如:class base .;class derive:base .;void main(void main()base obj1,*ptr;derive obj2;ptr=&obj1;ptr=&obj2;/不能自动指向其私有派生类
11、对象,但可 /强制转换,例如ptr=(base*)&obj2。第16页,共80页,编辑于2022年,星期三子类型子类型 如果一个特定的类型S,当且仅当它提供了类型T的行为时,则称类型S S是类型是类型T T的的子类型子类型。子类型体现了类型间的一般与特殊的关系。子类型体现了类型间的一般与特殊的关系。在C+中,子子类类型型的概念是通通过过公公有有继继承承(或公有派生)来实现实现的。根据继承方式的概念,我们知道,按公有继承的方式产生的派生类中,必然包含了原来基类中的全部成员。因此,一个公有派生类的对象可以提供其基类对象的全部行为(基类的全部接口),也就是说,在在程程序序中中可可以以把把一一个个公公
12、有有派派生生类类对对象象当当作作其其基基类类对对象象来来处处理。理。TS公有继承第17页,共80页,编辑于2022年,星期三例例:子类型的概念及实现示例。#include class A /定义类Aprivate:int a;public:A(int i=0)a=i;void print();void A:print()coutIn class A,print()is called.Show();basep-Show()基类指针基类指针派生类对象派生类对象基类对象基类对象第24页,共80页,编辑于2022年,星期三class Pointfloat x,y;public:Point()Point
13、(float i,float j)x=i;y=j;float area(void)return 0.0;const float Pi=3.14159;class Circle:public Point/类类Point的派生类的派生类float radius;public:Circle(float r)radius=r;float area(void)return Pi*radius*radius;void main(void)Point*pp;/基类指针,可以将派生类对象的地址赋给基类指针基类指针,可以将派生类对象的地址赋给基类指针 Circle c(5.4321);pp=&c;coutare
14、a()Show()Base*basep;basep=&b;basep=&d;basep-Show();即指向派生类新增的成员函数即指向派生类新增的成员函数需要将基类中的需要将基类中的Show()说明为虚函数说明为虚函数第30页,共80页,编辑于2022年,星期三class Point float x,y;public:Point()Point(float i,float j)x=i;y=j;virtual float area(void)return 0.0;const float Pi=3.14159;class Circle:public Point/类类Point的派生类的派生类floa
15、t radius;public:Circle(float r)radius=r;float area(void)return Pi*radius*radius;void main(void)Point*pp;/基类指针,可以将派生类对象的地址赋给基类指针基类指针,可以将派生类对象的地址赋给基类指针 Circle c(5.4321);pp=&c;coutarea()endl;/调用虚函数调用虚函数将将area()声明为虚函数,编译器对其进行动态聚束,按照实际对象声明为虚函数,编译器对其进行动态聚束,按照实际对象c调用了调用了Circle中的函数中的函数area()。使。使Point类中的类中的a
16、rea()与与Circle类中的类中的area()有一个统一的接口。有一个统一的接口。输出:输出:92.7011声明为虚函数声明为虚函数调用虚函数调用虚函数虚函数再定义虚函数再定义第31页,共80页,编辑于2022年,星期三#include class base public:virtual void who()cout basen;/定义虚函数virtual void show()cout “properties of base:n;/定义虚函数;class first:public base public:void who()cout the first derivationn;/重新定义
17、虚函数;第32页,共80页,编辑于2022年,星期三class second:public firstpublic:void who()cout who();/调用base 类的who()版本ptr-show();/调用base 类的show()版本ptr=&obj2;ptr-who();/调用first 类的who()版本ptr-show();/调用base 类的show()版本第34页,共80页,编辑于2022年,星期三ptr=&obj3;ptr-who();/调用second 类的who()版本ptr-show();/调用base 类的show()版本return 0;执行结果:base
18、properties of base:the first derivationproperties of base:the second derivationproperties of base:第35页,共80页,编辑于2022年,星期三得到上述理想的动态多态性结果的原因是:定义了虚函数的基类增加了一个存放虚函数调用地址函数指针表virtual table,该表的大小取决于虚函数的个数,该表的首地址由基类的内部指针vptr 指示。在派生层次中的各个派生类会从基类中直接或间接继承虚函数指针表virtual table 和指针vptr。如果虚函数在派生类被重新定义,则virtual table
19、中的调用地址将被重新定义虚函数的调用地址替换,否则仍然使用直接基类虚函数的调用地址。第36页,共80页,编辑于2022年,星期三 调用虚函数的运行绑定是由基类指针动态指向派生层次中某个类的对象,通过该对象的内部指针vptr 所指示的virtual table 中的相应调用地址实现的。下图示意了虚函数的定义和调用绑定关系:第37页,共80页,编辑于2022年,星期三第38页,共80页,编辑于2022年,星期三2 虚函数与重载函数的区别 虚函数的首次定义和重新定义实际上是在类派生定义层次中的同名函数覆盖定义。因此,虚函数的首次定义必须在基类中,重新定义只能在基类的不同派生类中,而不能发生在同一类定
20、义中,也不能是全局函数。而函数重载既可以发生在同一类定义中,也可以是全局函数。第39页,共80页,编辑于2022年,星期三 函数重载必须具有相同的函数名和不同的参数(个数、类型或顺序)。而函数的返回类型不是区别重载函数不同版本的标志,但如果两个函数只是返回类型不同,则会导致二义性错误。而虚函数重新定义必须保持与基类中的虚函数原型(返回类型、函数名、参数类型以及个数和顺序)完全一致,否则会产生两种情况:如果仅返回类型不同,则会导致二义性错误。如果仅函数名相同,而函数的参数有所不同,则系统会将该函数作为一般的重载函数处理,从而失去虚函数特性。第40页,共80页,编辑于2022年,星期三归纳虚函数的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第六 多态性 函数 PPT 讲稿
限制150内