第5章-多态性与虚函数PPT文档格式.ppt
- 文档编号:13124590
- 上传时间:2022-10-06
- 格式:PPT
- 页数:41
- 大小:482KB
第5章-多态性与虚函数PPT文档格式.ppt
《第5章-多态性与虚函数PPT文档格式.ppt》由会员分享,可在线阅读,更多相关《第5章-多态性与虚函数PPT文档格式.ppt(41页珍藏版)》请在冰豆网上搜索。
本章着重讲解运行时多态性。
5,5.2基类与派生类对象之间的赋值兼容关系在一定条件下,不同类型的数据之间可以进行类型转换,例如inti=10;
doublex=i;
不同类型数据之间的自动转换和赋值,称为赋值兼容。
在基类和派生类对象之间也存有赋值兼容关系。
把一个整型数(int)转换为双精度型数(double),然后再把它赋给双精度型变量。
6,具体表现在以下几个方面:
(1)可以用派生类对象给基类对象赋值。
例如:
例5-1Baseb;
/定义基类Base的对象bDerivedd;
/定义公有派生类Derived的对象db=d;
这样赋值的效果是,对象b中数据成员将具有对象d中对应数据成员的值。
用派生类对象d对基类对象b赋值,7,说明:
所谓赋值仅仅指对基类的数据成员赋值。
8,
(2)可以用派生类对象来初始化基类对象的引用。
例如5-2:
Baseb;
/定义基类Base的公有派生类/Derived的对象dBase,定义基类Base的对象的引用br,并用派生类Derived的对象d对其初始化,9,(3)派生类对象的地址可以赋给指向基类对象的指针。
例如,例5-3:
Derivedd;
/定义基类Base的公有派生类/Derived的对象dBase*bp=,把派生类对象的地址&
d赋值给指向基类的指针bp,也就是说,使指向基类对象的指针bp指向派生类对象d。
10,(4)声明为指向基类对象的指针可以指向它的公有派生的对象,但不允许指向它的私有派生的对象。
classBase;
classDerive:
privateBase;
intmain()Baseop1,*ptr;
Deriveop2;
ptr=,定义基类Base的对象op1及指向基类Base的指针ptr,定义派生类Derive的对象op2,错误,不允许将指向基类Base的指针ptr指向它的私有派生类对象op2,将指针ptr指向基类对象op1,11,(5)允许将一个声明为指向基类的指针指向其公有派生类的对象,但是不能将一个声明为指向派生类对象的指针指向其基类的对象。
classDerived:
publicBase;
intmain()Baseobj1;
Derivedobj2,*ptr;
ptr=,定义基类对象obj1,将指向派生类对象的指针ptr指向派生类对象obj2,定义派生类对象obj2及指向派生类的指针ptr,错误,试图将指向派生类对象的指针ptr指向其基类对象obj1,12,(6)在C+中规定:
基类的对象指针可以指向它的公有派生的对象,但是当其指向公有派生类对象时,它只能访问派生类中从基类继承来的成员,而不能访问公有派生类中定义的成员,例如:
classApublic:
voidprint1().;
classB:
publicApublic:
voidprint2().;
voidmain()A*p1;
/定义基类A的指针变量p1Bop2;
/定义派生类B的对象op2p1=,正确,基类指针变量p1可以访问派生类中从基类继承来的成员函数print1(),错误,基类指针变量p1不能访问派生类中定义的成员函数print2(),13,/例5-5静态联编#includeclassApublic:
voidprint()coutAprint().endl;
classB:
publicApublic:
voidprint()coutBprint().endl;
5.3.1虚函数的引入,voidmain()Ap,*p1;
p1=/输出?
例5-5,分析程序:
基类指针p1指向公有派生类对象op2时,只能访问op2中从基类继承来的成员。
这是静态联编的结果。
即,在程序编译阶段,对p1所指向的对象所执行的print()操作只能束定到从类A中的继承到的print()函数上。
所以输出不期望的结果。
14,/例5-6动态联编#includeclassApublic:
virtualvoidprint()coutAprint().endl;
virtualvoidprint()coutBprint().endl;
解决办法,voidmain()Ap,*p1;
分析程序:
静态联编中,程序在编译阶段并不确切知道要调用的函数,只有在执行时才确定将要调用的函数。
因此,要确切知道该调用的函数,要求联编工作在程序运行时进行,即动态联编。
C+规定动态联编是在虚函数的支持下实现的。
例5-6,被关键字virtual说明的函数称为虚函数。
这就意味着该成员函数在派生类中可能有不同的定义。
15,#includeclassPointpublic:
Point(inti,intj)x=i;
y=j;
intArea()return0;
private:
intx,y;
classRectangle:
publicPointpublic:
Rectangle(inti,intj,intk,intl):
Point(i,j)w=k;
h=l;
intArea()returnw*h;
intw,h;
5.3.1虚函数的引入,voidfun(Point,例5-4,分析程序:
在fun()函数中,s所引用对象执行的Area()操作被关联到point:
Area()的实现代码上。
在程序编译阶段,对s所引用的对象所执行的Area()操作只能束定到point类的函数上。
16,#includeclassPointpublic:
virtualintArea()return0;
virtualintArea()returnw*h;
解决办法,voidfun(Point,例5-4,分析程序:
由于说明了虚函数,所以在fun()函数中的引用对象参数p被动态联编,该函数体内调用的area()函数是在运行中束定的。
且被确定为rect类中的area()函数。
例5-4-1,17,说明:
(1)通过定义虚函数来使用多态性机制时,派生类必须从它的基类公有派生。
(2)在基类中,声明虚函数原型(需加上virtual),而在类外定义虚函数时,则不必再加virtual。
例如:
classB0public:
virtualvoidprint(char*p);
voidB0:
print(char*p)coutpprint()endl;
在类外,定义虚函数时,不要加virtual,声明虚函数原型,需加上virtual,18,(3)如果在派生类中没有对基类的虚函数重新定义,则公有派生类继承其直接基类的虚函数。
一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性。
classB0.public:
virtualvoidshow().;
classB1:
publicB0.;
若在公有派生类B1中没有重新定义虚函数show,则函数show在派生类中被继承,仍是虚函数。
在基类B0中,定义show为虚函数,19,(4)在派生类中重新定义该虚函数时,关键字virtual可以写也可以不写。
但是,为了使程序更加清晰,最好在每一层派生类中定义该函数时都加上关键字virtual。
publicB0.virtualvoidshow().;
(5)虽然使用对象名和点运算符的方式也可以调用虚函数,但是这种调用是在编译时进行的,是静态联编,它没有利用虚函数的特性。
只有通过基类指针或引用访问虚函数时才能获得运行时的多态性。
在基类B0中,定义show为虚函数,在派生类中,重新定义虚函数show()时,最好也加上关键字virtual,20,(6)虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数,因为虚函数调用要靠特定的对象来决定该激活哪个函数。
(7)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
虚函数在编译时是非内联的。
(8)当派生类的虚函数与基类中对应的虚函数的参数不同时,派生类的虚函数将丢失虚特性。
(9)构造函数不能是虚函数,但是析构函数可以是虚函数,而且通常说明为虚函数。
总结:
动态联编的实现需要如下3个条件:
(1)类之间为基类与派生类的关系;
(2)要有虚函数;
(3)指针或者对象引用来操作函数。
21,声明虚析构函数的一般格式为:
说明:
(1)虚析构函数没有类型,也没有参数。
(2)如果将基类的析构函数定义为虚函数,由该基类所派生的所有派生类的析构函数也都自动成为虚函数。
(3)声明虚析构函数的目的在于使用delete运算符删除一个对象时,能保证析构函数被正确执行。
virtual类名()函数体,5.3.2虚析构函数,22,#includeclassApublic:
virtualA()coutA().endl;
publicAchar*buf;
public:
B(inti)buf=newchari;
virtualB()deletebuf;
coutB().endl;
voidmain()A*a=newB(10);
deletea;
虚析构函数,例5-7,
(1)析构函数未说明virtual时,该语句采用静态联编。
即,此时删除A类对象。
只输出:
A().
(2)析构函数说明virtual时,该语句采用动态联编。
即,此时删除B类对象。
输出B().A().,23,5.4.1纯虚函数1.纯虚函数的引例例5-8应用C+的虚函数,计算三角形、矩形和圆的面积。
圆类Circle虚函数area(),三角形类Triangle虚函数area(),矩形类Square虚函数area(),基类Figure虚函数area(),24,classFigureprotected:
doublex,y;
Figure(doublea,doubleb)x=a;
y=b;
virtualvoidarea()cout在基类中定义的虚函数n;
定义一个公共基类Figure,定义虚函数area(),为派生类提供一个公共接口,以便派生类根据需要
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多态性 函数
