您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 下载-第五章多态性和虚函数解读
45实验四多态性与虚函数一、实验目的和要求1了解多态性在C++中的体现;2掌握虚函数的应用;3了解抽象类。二、基本概念多态性多态是指同样的消息被不同类型的对象接收时导致不同的行为,所谓消息是指对类的成员函数调用,不同的行为是指不同的实现,也就是调用了不同的函数。多态性可以分为四类:重载多态、强制多态、包含多态和参数多态。多态从实现的角度来讲可以划分为两类:编译时的多态和运行时的多态。编译时的多态性是在编译的过程中确定了同名操作的具体操作对象,也就是通过重载函数来实现的。运行时的多态性是在程序运行过程中才动态地确定操作所针对的具体对象,就是用虚函数来实现的。虚函数虚函数是重载的另一种表现形式,它是一种动态的重载方式,它提供了一种更为灵活的多态性机制。虚函数允许函数调用与函数体之间的联系在运行时才建立,也就是在运行时才决定如何动作,即所谓的“动态连接”。一般虚函数成员的定义语法是:virtual函数类型函数名(形参表)虚函数的定义实际就是在原有的普通函数成员前面使用virtual关键字来限定,虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员的函数体中。运行过程中的多态需要满足三个条件,首先类之间应满足赋值兼容规则,其二是要声明虚函数,第三是要由成员函数来调用或者是通过指针、引用来访问虚函数。抽象类抽象类是一种特殊的类,它为一族类提供统一的操作界面。一个抽象类自身无法实例化,也就是说我们无法定义一个抽象类的对象,只能通过继承机制,生成抽象类的非抽象派生类,然后再实例化。抽象类是带有纯虚函数的类。纯虚函数是一个基类中说明的虚函数,它在该基类中没有定义具体的操作内容,要求各派生类必须根据实际需要定义自己的版本,纯虚函数的声明格式为:virtual函数类型函数名(参数表)=0;声明为纯虚函数之后,基类中就不再给出函数的实现部分,它的实现是在它的派生类定义的。46对抽象类使用的几点规定如下:1抽象类只能用作其他类的基类,不能建立抽象类对象;2抽象类不能用作参数类型、函数返回类型或显式转换的类型;3可以说明指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性一般虚函数成员的定义语法是:virtual函数类型函数名(形参表)纯虚函数的声明格式为:virtual函数类型函数名(参数表)=0;三、程序例题例题4.1有一个汽车类Vehicle,将它作为基类派生出小车类Car、卡车为类Truck和轮船类Boat,定义message()函数用来显示各类信息。解:程序设计如下:(1)在基类汽车类Vehicle类中,定义一个虚函数message(),用来显示信息;(2)在各个派生类中,重新定义message()函数,以显示各自的信息;(3)在测试函数中,定义基类指针ptr,当它指向不同的对象时,则执行不同对象所对应类的成员函数message()。程序实现:#includeiostream.hclassVehicle//车辆类Vehicle定义{public:virtualvoidmessage(){coutVehiclemessage\n;}private:intwheels;floatweigth;};//汽车类Car定义classCar:publicVehicle{public:voidmessage(){coutCarmessage\n;}private:intpassenger_load;};//卡车类Truck定义classTruck:publicVehicle{public:voidmessage(){coutTruckmessage\n;}private:intpassenger_load;floatpayload;};47//轮船类Boat定义classBoat:publicVehicle{intpassenger_load;public:voidmessage(){coutBoatmessage\n;}};voidmain(){Vehiclevehicle,*ptr;//定义一个基类Vehicle对象vehicle和基类指针ptrCarcar;//定义一个Car类对象carTrucktruck;//定义一个Truck类对象truckBoatboat;//定义一个Boat类对象boatptr=&vehicle;//将指针ptr指向基类对象ptr-message();//调用基类成员函数ptr=&car;//将指针ptr指向Car类对象ptr-message();//调用Car类成员函数ptr=&truck;//将指针ptr指向Truck类对象ptr-message();//调用Truck类成员函数ptr=&boat;//将指针ptr指向boat类对象ptr-messag();//调用Boat类成员函数}程序运行结果:例4.2从基类的图形类中派生出两个类。一个派生类是矩形类,在该类中,基类的x,y做作矩形的长和宽;另一个派生类是圆类,在该类中,新添加了成员是半径radius,半径的值等于x,y的坐标到原点的距离。程序实现:#includeiostream.h#includemath.hclassGraph//定义一个图形基类{floatx,y;public:Graph(floatxx,floatyy){x=xx;y=yy;}floatarea(){return0;}};classRect:publicGraph//由图形类派生出立方体{floatlength,width,high;public:Rect(floatx,floaty):Graph(x,y){length=x;width=y;48}floatarea(){returnlength*width;}};classCircle:publicGraph//由图形类派生出圆类{doubleradius;public:Circle(floatx,floaty):Graph(x,){radius=sqrt(x*x+y*y);}doublearea(){return3.1416*radius*radius;}};voidmain(){Graphs0(10,10);Rects1(10,10);Circles2(10,10);cout原面积=s0.area()endl;//调用基类的area()cout矩形面积=s1.area()endl;//调用矩形的area()cout圆的面积=s2.area()endl;//调用圆类的area()cout面积=s2.Graph::area()endl;//调用基类的area()}程序运行结果为:在上题中,虽然在这三个类中都有一个求面积的同名函数area(),函数所带的参数也相同,但它们是属于不同的类。在编译时函数area()就确定了其对象,各个对象调用其相应的函数,因此所得的结果也不同。这一点从上面的结果可以看出。例题4.3修改上题的基类,将Graph类定义为抽象类,其他要求不变。解:程序具体设计如下:(1)在抽象类Graph类中,定义两个纯虚函数Area()和Display()。(2)在各派生类中,根据各自不同的要求,定义Area()和Display()函数的具体操作。(3)在主函数中,定义基类的指针数组ptr[2],使它指向不同派生类的对象,以便在程序运行过程中,执行不同对象所对应的类的成员函数。程序实现:#includeiostream.h#includemath.hclassGraph//定义一个图形基类{doublex,y;public:Graph(doublexx,doubleyy){x=xx;y=yy;}virtualdoubleArea()=0;//纯虚函数virtualvoidDisplay()=0;//纯虚函数};49classRect:publicGraph//由图形类派生出立方体{doublelength,width;public:Rect(doublex,doubley):Graph(x,y){length=x;width=y;}doubleArea(){returnlength*width;}voidDisplay(){cout矩形面积=;}};classCircle:publicGraph//由图形类派生出圆类{doubleradius;public:Circle(doublex,doubley):Graph(x,y){radius=sqrt(x*x+y*y);}doubleArea(){return3.1416*radius*radius;}voidDisplay(){cout圆形面积=;}};voidmain(){Graph*ptr[2];;//定义抽象类指针Rects1(10,10);//矩形类对象Circles2(10,10);//圆形类对象ptr[0]=&s1;//指针指向矩形类对象ptr[1]=&s2;//指针指向圆形类对象intflag=0,choice;while(flag!=3){coutendl;cout1.矩形面积endl;cout2.圆形面积endl;cout3.退出endl;cout请选择(1-3):;cinchoice;if(choice==3)flag=3;elseif(choice=1&&choice3){ptr[choice-1]-Display();coutptr[choice-1]-Area()endl;}elsecout选择不在范围内,请重新选择。endl;}}程序运行结果:50例4.4计算教师工资。教授类计算的是教授的工资,由该类派生出的讲师类计算的是讲师的工资。解:(1)程序设计了一个类Professor,其成员函数Preliminary()为虚函数,该函数用于计算教师的工资,Disp()用于显示教师的收入。(2)设计一个Prelector类,它是从Professor类派生的,其中的Preliminary()函数用于计算讲师的收入,这时的Disp()用于显示讲师的收入。定义一个Print()函数,通过传递参数的不同,可调用不同的显示函数。就是说,在执行Print()时,根据p对象的不同,自动确定调用相应的成员函数。程序实现:#includeiostream.hclassProfessor{protected:intNo;charname[10];intf1,f2,f3,f;public:virtualvoidPreliminary(){cout编号:;cinNo;cout姓名:;cinname;f1=2000;f2=500;f3=100;f=f1+f2-f3;}51voidDisp(){cout基本工资:f1endl;cout岗位津贴:f2endl;cout实发工资:fendl;}};classPrelecto:publicProfessor{public:voidPreliminary(){cout编号:;cinNo;cout姓名:;cinname;f1=1500;f2=300;f3=80;f=f1+f2-f3;}voidDisp(){cout基本工资:f1endl;cout岗位津贴:f2endl;cout实发工资:fendl;}};voidPrint(Professor&p){p.Preliminary();p.Disp();}voidmain(){Professorp1;Prelectorp2;cout教授的工资:endl;Print(p1);//计算教授的工资cout讲师的工资:endl;Print(p2);//计算讲师的工资}程序运行结果:52例题4.5程序设计了一个抽象类图形类,由这个抽象类派生出矩形、圆形和三角形三个类。在抽象类中定义了公
本文标题:下载-第五章多态性和虚函数解读
链接地址:https://www.777doc.com/doc-6156639 .html