第8章2━━多态性与虚函数课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《第8章2━━多态性与虚函数课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多态性 函数 课件
- 资源描述:
-
1、C+C+程序设计程序设计第第8 8章章(2)(2)多态性与虚函数多态性与虚函数主要内容主要内容l C+C+的多态性的多态性l 动态多态性的实现条件动态多态性的实现条件l 虚函数的声明虚函数的声明l 虚函数的特性与调用虚函数的特性与调用l 静态关联、动态关联静态关联、动态关联l 虚析构函数虚析构函数l 纯虚函数纯虚函数l 抽象类抽象类l 综合实例综合实例C+C+的多态性的多态性l 多态性:多态性:指对不同类型的对象发送同样的消息(即调用同名的函数),不同类型的指对不同类型的对象发送同样的消息(即调用同名的函数),不同类型的对象在接收时会产生不同的行为(即执行各自同名的函数)。对象在接收时会产生不
2、同的行为(即执行各自同名的函数)。l 编译时多态性(静态多态性):编译时多态性(静态多态性):指在编译阶段,系统就可根据所操作的对象,确定指在编译阶段,系统就可根据所操作的对象,确定其具体的操作。其具体的操作。编译时多态性是通过函数重载、运算符重载来实现的。编译时多态性是通过函数重载、运算符重载来实现的。函数重载是函数重载是根据函数调用式中所给出的实参的类型或实参的个数,在编译阶段系统就可确定调根据函数调用式中所给出的实参的类型或实参的个数,在编译阶段系统就可确定调用的是同名函数中的哪一个。运算符重载是根据运算式中所给出的运算对象的类型,用的是同名函数中的哪一个。运算符重载是根据运算式中所给出
3、的运算对象的类型,在编译阶段系统就可确定执行的是同种运算中的哪一个。在编译阶段系统就可确定执行的是同种运算中的哪一个。l 运行时多态性(动态多态性):运行时多态性(动态多态性):指在编译阶段,系统仅根据函数调用式是无法确定指在编译阶段,系统仅根据函数调用式是无法确定调用的是同名函数中的哪一个;必须在程序运行过程中,动态确定所要调用函数的调用的是同名函数中的哪一个;必须在程序运行过程中,动态确定所要调用函数的当前对象,并根据当前对象的类型来确定调用的是同名函数中的哪一个。当前对象,并根据当前对象的类型来确定调用的是同名函数中的哪一个。运行时多运行时多态性是通过态性是通过“类的继承关系类的继承关系
4、”加上加上“虚函数虚函数”联合起来实现的。联合起来实现的。动态多态性的实现条件动态多态性的实现条件l 要有类的继承层次结构:要有类的继承层次结构:一个基类可以派生出不同的派生类,各派生类中可以新增一个基类可以派生出不同的派生类,各派生类中可以新增与基类中的函数名字相同、参数个数及类型也相同的成员,这些同名的成员函数在与基类中的函数名字相同、参数个数及类型也相同的成员,这些同名的成员函数在不同的派生类中就有不同的含义!这样,不同的派生类中就有不同的含义!这样,在类的继承结构中,不同的层次上出现了在类的继承结构中,不同的层次上出现了名字相同、参数个数及类型也相同、但功能不同的函数!名字相同、参数个
5、数及类型也相同、但功能不同的函数!l 引入虚函数:引入虚函数:作用是在由一个基类派生出的类体系中实现作用是在由一个基类派生出的类体系中实现“一个接口,多种方法一个接口,多种方法”,主要用于建立通用程序。对于同一类体系中的各层次派生类,使用虚函数可实现统主要用于建立通用程序。对于同一类体系中的各层次派生类,使用虚函数可实现统一的类接口,以便用相同的方式对各层次派生类的对象进行操作。一的类接口,以便用相同的方式对各层次派生类的对象进行操作。虚函数是基类的虚函数是基类的成员函数,是为了实现某一种功能而假设的虚拟函数,在该基类的各层次派生类中成员函数,是为了实现某一种功能而假设的虚拟函数,在该基类的各
6、层次派生类中对该虚函数可有各自不同的定义对该虚函数可有各自不同的定义!l 要能体现虚函数的特性:要能体现虚函数的特性:必须通过基类的对象指针、基类的对象引用来调用各层次必须通过基类的对象指针、基类的对象引用来调用各层次派生类对象的同名虚函数,才能体现虚函数的特性!派生类对象的同名虚函数,才能体现虚函数的特性!因为只有这样才能用相同的调因为只有这样才能用相同的调用方式去调用不同层次派生类对象的同名虚函数,从而实现动态多态性。用方式去调用不同层次派生类对象的同名虚函数,从而实现动态多态性。虚函数的声明虚函数的声明l 虚函数的声明:虚函数的声明:class 基类基类 virtual 返回值类型返回值
7、类型 成员函数名成员函数名 (形参表形参表)函数体函数体 ;当一个基类的某成员函数声明为虚函数,则在该基类的所有派生类中,与虚函数同当一个基类的某成员函数声明为虚函数,则在该基类的所有派生类中,与虚函数同名、参数个数及类型相同、且返回值类型也相同的,不论是否有关键字名、参数个数及类型相同、且返回值类型也相同的,不论是否有关键字 virtual 修饰,修饰,都是虚函数,反之不然。但要注意:若在派生类中只是与虚函数同名,而参数个数都是虚函数,反之不然。但要注意:若在派生类中只是与虚函数同名,而参数个数或类型有不同时,属于函数重载,不是虚函数!或类型有不同时,属于函数重载,不是虚函数!virtual
8、 只是用在类中声明虚函数,若在类外定义虚函数前面不要加只是用在类中声明虚函数,若在类外定义虚函数前面不要加 virtual。构造函数、静态成员函数不能声明为虚函数!析构函数可以声明为虚函数。构造函数、静态成员函数不能声明为虚函数!析构函数可以声明为虚函数。虚函数的特性与调用虚函数的特性与调用l 如何体现虚函数的特性?如何体现虚函数的特性?只有通过基类的对象指针、基类的对象引用来调用派生类只有通过基类的对象指针、基类的对象引用来调用派生类对象的虚函数时,才能体现虚函数的特性!而通过派生类对象的对象名、对象指针、对象的虚函数时,才能体现虚函数的特性!而通过派生类对象的对象名、对象指针、对象引用来调
9、用虚函数时,无法体现虚函数的特性!对象引用来调用虚函数时,无法体现虚函数的特性!l 派生类对象中派生类对象中一般成员函数一般成员函数的调用的调用方法:方法:可通过派生类对象的对象名、对象指针、对象引用来调用!调用过程:若派生类新可通过派生类对象的对象名、对象指针、对象引用来调用!调用过程:若派生类新增成员函数中存在该函数,则被调用;若不存在,则调用上一层基类中的该函数;增成员函数中存在该函数,则被调用;若不存在,则调用上一层基类中的该函数;若这一层基类中也不存在,就继续往上一层寻找若这一层基类中也不存在,就继续往上一层寻找 ,直至找到该函数并被调用。,直至找到该函数并被调用。l 派生类对象中派
10、生类对象中一般成员函数一般成员函数的调用的调用方法:方法:可通过基类的对象指针、基类的对象引用来调用派生类对象中的一般成员函数!但可通过基类的对象指针、基类的对象引用来调用派生类对象中的一般成员函数!但只能调用派生类中从该基类继承过来的那部分成员函数!只能调用派生类中从该基类继承过来的那部分成员函数!虚函数的特性与调用虚函数的特性与调用l 派生类对象中派生类对象中虚函数虚函数的调用的调用方法:方法:派生类对象的虚函数也是成员函数,可按一般成员函数的方式调用!即:可通过派派生类对象的虚函数也是成员函数,可按一般成员函数的方式调用!即:可通过派生类对象的对象名、对象指针、对象引用来调用!调用过程与
11、一般成员函数的调用生类对象的对象名、对象指针、对象引用来调用!调用过程与一般成员函数的调用过程相同!由此可见,这种调用方式无法体现虚函数的特性!过程相同!由此可见,这种调用方式无法体现虚函数的特性!l 派生类对象中派生类对象中虚函数虚函数的调用的调用方法:方法:可通过基类的对象指针、基类的对象引用来调用派生类对象的虚函数!调用过程:可通过基类的对象指针、基类的对象引用来调用派生类对象的虚函数!调用过程:调用的是派生类中的虚函数!若派生类中没有重新定义该虚函数,则调用的是上一调用的是派生类中的虚函数!若派生类中没有重新定义该虚函数,则调用的是上一层基类中的该虚函数;若在这一层基类中也没有重新定义
12、该虚函数,就继续往上一层基类中的该虚函数;若在这一层基类中也没有重新定义该虚函数,就继续往上一层寻找层寻找 ,直至,直至基类的对象指针、基类的对象引用它们本身所属的那一层基类!基类的对象指针、基类的对象引用它们本身所属的那一层基类!l 动态多态性的实现:动态多态性的实现:可以让基类的对象指针(或基类的对象引用)先后指向(或先可以让基类的对象指针(或基类的对象引用)先后指向(或先后引用)同一类族中不同派生类的对象,以便用相同的调用方式去调用不同派生类后引用)同一类族中不同派生类的对象,以便用相同的调用方式去调用不同派生类对象中的同名虚函数,从而实现动态多态性。对象中的同名虚函数,从而实现动态多态
13、性。【例】(派生类对象中【例】(派生类对象中一般成员函数一般成员函数的调用的调用方法:可通过派生类对象的对象名、方法:可通过派生类对象的对象名、对象指针、对象引用来调用!注意调用过程。)对象指针、对象引用来调用!注意调用过程。)#includeclass A int x;public:A(int a)x=a;void g()cout “A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;void f()cout “B:y=”y endl;class C:public B int m;public:C(int a,in
14、t b,int c):B(a,b)m=c;void g()cout “C:m=”m endl;class D:public C int n;public:D(int a,int b,int c,int d):C(a,b,c)n=d;void f()cout “D:n=”n f();pd-g();D&dd1=d1;dd1.f();dd1.g();运行:运行:D:n=4C:m=3D:n=4C:m=3D:n=4C:m=3 从从A类继承的成员:类继承的成员:int x;g();不是虚函数不是虚函数从从B类继承的成员:类继承的成员:int y;f();不是虚函数不是虚函数从从C类继承的成员:类继承的成员
15、:int m;g();不是虚函数不是虚函数D类新增的成员:类新增的成员:int n;f();不是虚函数不是虚函数 pdd1对象对象 dd1【例】(派生类对象中【例】(派生类对象中虚函数虚函数的调用的调用方法:可通过派生类对象的对象名、对象指方法:可通过派生类对象的对象名、对象指针、对象引用来调用!注意调用过程与一般成员函数相同!由此可见,这种调用方针、对象引用来调用!注意调用过程与一般成员函数相同!由此可见,这种调用方式无法体现虚函数的特性!)式无法体现虚函数的特性!)#includeclass A int x;public:A(int a)x=a;virtual void g()cout “
16、A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;virtual void f()cout “B:y=”y endl;class C:public B int m;public:C(int a,int b,int c):B(a,b)m=c;void g()cout “C:m=”m endl;class D:public C int n;public:D(int a,int b,int c,int d):C(a,b,c)n=d;void f()cout “D:n=”n f();pd-g();D&dd1=d1;dd1.
17、f();dd1.g();运行:运行:D:n=4C:m=3D:n=4C:m=3D:n=4C:m=3 从从A类继承的成员:类继承的成员:int x;g();虚函数虚函数从从B类继承的成员:类继承的成员:int y;f();虚函数虚函数从从C类继承的成员:类继承的成员:int m;g();虚函数虚函数D类新增的成员:类新增的成员:int n;f();虚函数虚函数 pdd1对象对象 dd1【例】(派生类对象中【例】(派生类对象中一般成员函数一般成员函数的调用的调用方法:可通过基类的对象指针、基类方法:可通过基类的对象指针、基类的对象引用来调用!但只能调用派生类中从该基类继承来的那部分成员函数!)的对象
18、引用来调用!但只能调用派生类中从该基类继承来的那部分成员函数!)#includeclass A int x;public:A(int a)x=a;void g()cout “A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;void g()cout “B:y=”y endl;class C:public B int z;public:C(int a,int b,int c):B(a,b)z=c;void g()cout “C:z=”z endl;void f()cout “Bye!”g();aa1.g();/pa-
19、f();为什么不行?为什么不行?B *pb=&c1,&bb1=c1;pb-g();bb1.g();/pb-f();为什么不行?为什么不行?C *pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();从从A类继承的成员:类继承的成员:int x;g();不是虚函数不是虚函数从从B类继承的成员:类继承的成员:int y;g();不是虚函数不是虚函数C类新增的成员:类新增的成员:int z;g();不是虚函数不是虚函数f();不是虚函数不是虚函数 pb pa pcC1对象对象运行:运行:A:x=1A:x=1B:y=2B:y=2C:z=3C:z=3 Bye!【例】(派生类对象中【例
20、】(派生类对象中虚函数虚函数的调用的调用方法:可通过基类的对象指针、基类的对象方法:可通过基类的对象指针、基类的对象引用来调用!注意:引用来调用!注意:调用的是派生类中的虚函数!若派生类中没有重新定义该虚函调用的是派生类中的虚函数!若派生类中没有重新定义该虚函数,则调用的是上一层基类中的该虚函数,数,则调用的是上一层基类中的该虚函数,)#includeclass A int x;public:A(int a)x=a;virtual void g()cout “A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;voi
21、d g()cout “B:y=”y endl;class C:public B int z;public:C(int a,int b,int c):B(a,b)z=c;void g()cout “C:z=”z endl;virtual void f()cout “Bye!”g();aa1.g();/pa-f();为什么不行?为什么不行?B *pb=&c1,&bb1=c1;pb-g();bb1.g();/pb-f();为什么不行?为什么不行?C *pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();从从A类继承的成员:类继承的成员:int x;g();虚函数虚函数从从B类继
22、承的成员:类继承的成员:int y;g();虚函数虚函数C类新增的成员:类新增的成员:int z;g();虚函数虚函数f();虚函数虚函数 pb pa pcC1对象对象运行:运行:C:z=3C:z=3C:z=3C:z=3C:z=3C:z=3 Bye!【例】(请注意调用过程。)【例】(请注意调用过程。)#includeclass A int x;public:A(int a)x=a;virtual void g()cout “A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;void g()cout “B:y=”y
23、endl;class C:public B int z;public:C(int a,int b,int c):B(a,b)z=c;virtual void f()cout “Bye!”g();aa1.g();/pa-f();为什么不行?为什么不行?B *pb=&c1,&bb1=c1;pb-g();bb1.g();/pb-f();为什么不行?为什么不行?C *pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();从从A类继承的成员:类继承的成员:int x;g();虚函数虚函数从从B类继承的成员:类继承的成员:int y;g();虚函数虚函数C类新增的成员:类新增的成员:i
24、nt z;f();虚函数虚函数 pb pa pcC1对象对象运行:运行:B:y=2B:y=2B:y=2B:y=2B:y=2B:y=2Bye!【例【例】(请注意调用过程。)(请注意调用过程。)#includeclass A int x;public:A(int a)x=a;void g()cout “A:x=”x endl;class B:public A int y;public:B(int a,int b):A(a)y=b;virtual void g()cout “B:y=”y endl;class C:public B int z;public:C(int a,int b,int c):
25、B(a,b)z=c;void g()cout “C:z=”z endl;void f()cout “Bye!”g();aa1.g();/pa-f();为什么不行?为什么不行?B *pb=&c1,&bb1=c1;pb-g();bb1.g();/pb-f();为什么不行?为什么不行?C *pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();从从A类继承的成员:类继承的成员:int x;g();不是虚函数不是虚函数从从B类继承的成员:类继承的成员:int y;g();虚函数虚函数C类新增的成员:类新增的成员:int z;g();虚函数虚函数f();不是虚函数不是虚函数 pb p
展开阅读全文