《面向对象程序设计C++》课件1第5章 多态性与虚函数.ppt
《《面向对象程序设计C++》课件1第5章 多态性与虚函数.ppt》由会员分享,可在线阅读,更多相关《《面向对象程序设计C++》课件1第5章 多态性与虚函数.ppt(57页珍藏版)》请在文库网上搜索。
1、2023/12/21第第5章章 多态性与虚函数多态性与虚函数什么是多什么是多态性性向上向上类型型转换 功能早功能早绑定和晚定和晚绑定定实现功能晚功能晚绑定定虚函数虚函数 纯虚函数和抽象虚函数和抽象类 图书馆图书借借阅管理系管理系统中的多中的多态性性本章学习要点本章学习要点2023/12/22本章学习目标本章学习目标理解多态性的概念掌握虚函数的使用理解纯虚函数和抽象类的概念掌握纯虚函数和抽象类的使用第第6章章 面向对象的妥协面向对象的妥协2023/12/23第第5章章 多态性与虚函数多态性与虚函数在面向在面向对象方法中象方法中一般是一般是这样表述表述多多态性性的:的:向不同的向不同的对象象发送同
2、一个消息,不同的送同一个消息,不同的对象在接象在接收收时会有不同的反会有不同的反应,产生不同的生不同的动作。作。也就是也就是说,每个,每个对象可以用自己的方式去响象可以用自己的方式去响应共同的消共同的消息。息。在在C+程序程序设计中中,多多态性性是指用一个名字定是指用一个名字定义不同的函数,不同的函数,这些函数些函数执行不同但又行不同但又类似的操似的操作,从而可以使用相同的作,从而可以使用相同的调用方式来用方式来调用用这些具些具有不同功能的同名函数。有不同功能的同名函数。实现“一个接口,多种方法一个接口,多种方法”2023/12/245.1 什么是多态性什么是多态性C+中的多中的多态性可以分性
3、可以分为4类:参数多参数多态包含多包含多态重重载多多态强制多制多态2023/12/255.1 什么是多态性什么是多态性 参数多参数多态 如函数模板和如函数模板和类模板。模板。l由函数模板由函数模板实例化的各个函数都具有相例化的各个函数都具有相同的操作,而同的操作,而这些函数的参数些函数的参数类型却各不型却各不相同。同相同。同样地,由地,由类模板模板实例化的各个例化的各个类都具有相同的操作,而操作都具有相同的操作,而操作对象的象的类型是型是各不相同的。各不相同的。2023/12/265.1 什么是多态性什么是多态性包含多包含多态l是研究是研究类族中定族中定义于不同于不同类中的同名成中的同名成员函
4、数的多函数的多态行行为,主要是通,主要是通过虚函数来虚函数来实现的。的。2023/12/275.1 什么是多态性什么是多态性重重载多多态l如函数重如函数重载、运算符重、运算符重载等。前面我等。前面我们学学习过的普通函数及的普通函数及类的成的成员函数的重函数的重载都属于重都属于重载多多态。2023/12/285.1 什么是多态性什么是多态性强制多制多态l是指将一个是指将一个变元的元的类型加以型加以变化,以符化,以符合一个函数(或操作)的要求,例如加法合一个函数(或操作)的要求,例如加法运算符在运算符在进行浮点数与整型数相加行浮点数与整型数相加时,首,首先先进行行类型型强制制转换,把整型数,把整型
5、数变为浮点浮点数再相加的情况,就是数再相加的情况,就是强制多制多态的的实例。例。2023/12/295.2 向上类型转换向上类型转换向上向上类型型转换是指把一个派生是指把一个派生类的的对象作象作为基基类的的对象来使用象来使用。向上向上转型中有三点需要我型中有三点需要我们特特别注意:注意:向上向上类型型转换是安全的。是安全的。向上向上类型型转换可以自可以自动完成。完成。向上向上类型型转换的的过程中会程中会丢失子失子类型信型信息。息。【例例5-1】一个向上一个向上类型型转换的例子。的例子。2023/12/2105.2 向上类型转换向上类型转换#include using namespace std
6、;class Point public:Point(double a=0,double b=0)x=a;y=b;double Area()cout Call Points Area function.endl;return 0.0;protected:double x,y;class Rectangle:public Point public:Rectangle(double a=0,double b=0,double c=0,double d=0):Point(a,b)x1=c;y1=d;double Area()cout Call Rectangles Area function.endl
7、;return(x-x1)*(y-y1);protected:double x1,y1;class Circle:public Point public:Circle(double a=0,double b=0,double c=0):Point(a,b)r=c;double Area()cout Call Circles Area function.endl;return 3.14*r*r;protected:double r;double CalcArea(Point&ref)return(ref.Area();int main()Point p(0,0);Rectangle r(0,0,
8、1,1);Circle c(0,0,1);cout CalcArea(p)endl;cout CalcArea(r)endl;cout CalcArea(c)endl;return 0;程序运行程序运行结果如下:果如下:Call Points Area function.0Call Points Area function.0Call Points Area function.0virtual程序运行程序运行结果如下:果如下:Call Points Area function.0Call Rectangles Area function.1Call Circles Area function.
9、3.142023/12/2115.3 功能早绑定和晚绑定功能早绑定和晚绑定v多多态性从性从实现的角度来的角度来讲可以划分可以划分为两两类:编译时的多的多态性性和和运行运行时的多的多态性性。v在在C+中,中,编译时的多的多态性性主要是主要是通通过函函数重数重载和运算符重和运算符重载实现的。的。运行运行时的多的多态性性主要是主要是通通过虚函数来虚函数来实现的。的。2023/12/2125.3 功能早绑定和晚绑定功能早绑定和晚绑定v功能早功能早绑定定(编译时的多的多态性性):绑定是在程序定是在程序编译阶段完成。段完成。功能早功能早绑定定时,系,系统用用实参与形参与形参参进行匹配,行匹配,对于同名的重
10、于同名的重载函数便根据参数函数便根据参数上的差异上的差异进行区分,然后行区分,然后进行行绑定,从而定,从而实现了了编译时的多的多态性。性。v功能晚功能晚绑定定(运行运行时的多的多态性性):绑定是在程序运定是在程序运行行阶段完成的。即当程序段完成的。即当程序调用到某一函数名用到某一函数名时,才去才去寻找和找和连接其程序代接其程序代码,对面向面向对象程序象程序设计而言,就是当而言,就是当对象接收到某一消息象接收到某一消息时,才,才去去寻找和找和连接相接相应的方法。的方法。2023/12/2135.4.1 虚函数的定义与使用虚函数的定义与使用v虚成虚成员函数的定函数的定义语法是:法是:virtual
11、 函数函数类型型 函数名函数名(形参表形参表)函数体函数体 虚函数的定虚函数的定义是在基是在基类中中进行的行的,在成,在成员函数原型的声函数原型的声明明语句之前冠以关句之前冠以关键字字virtual,从而提供一种接口。,从而提供一种接口。2023/12/214v当基当基类中的某个成中的某个成员函数被声明函数被声明为虚函数后,虚函数后,此虚函数就可以在一个或多个派生此虚函数就可以在一个或多个派生类中被重中被重新定新定义。在派生在派生类中重新定中重新定义时,其函数原其函数原型,包括返回型,包括返回类型、函数名、参数个数、参型、函数名、参数个数、参数数类型的型的顺序,都必序,都必须与基与基类中的原型
12、完全中的原型完全相同。相同。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/215v虚函数的作用虚函数的作用是允是允许在派生在派生类中重新定中重新定义与与基基类同名的函数,并且可以通同名的函数,并且可以通过基基类指指针或或引用来引用来访问基基类和派生和派生类中的同名函数中的同名函数。v具体做法是,首先在基具体做法是,首先在基类中声明中声明这个成个成员函函数数为虚函数,也就是在虚函数,也就是在这个成个成员函数前面函数前面缀上关上关键字字virtual,并在派生,并在派生类中被重新定中被重新定义,就能就能实现动态调用的功能。用的功能。5.4.1 虚函数的定义与使用虚函数的定义与使用
13、2023/12/216【例例5-2】虚函数的作用。虚函数的作用。#include using namespace std;class Pointpublic:Point(double a=0,double b=0)x=a;y=b;virtual double Area()cout Call Points Area function.endl;return 0.0;protected:double x,y;5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/217class Rectangle:public Pointpublic:Rectangle(double a=0,doubl
14、e b=0,double c=0,double d=0):Point(a,b)x1=c;y1=d;double Area()cout Call Rectangles Area function.endl;return(x1-x)*(y1-y);protected:double x1,y1;5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/218class Circle:public Pointpublic:Circle(double a=0,double b=0,double c=0):Point(a,b)r=c;double Area()cout Call Circles Ar
15、ea function.endl;return 3.14*r*r;protected:double r;5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/219double CalcArea(Point&ref)return(ref.Area();int main()Point p(0,0);Rectangle r(0,0,1,1);Circle c(0,0,1);cout CalcArea(p)endl;cout CalcArea(r)endl;cout CalcArea(c)endl;return 0;5.4.1 虚函数的定义与使用虚函数的定义与使用程序运行程序运行结果如下:
16、果如下:Call Points Area function.0Call Rectangles Area function.1Call Circles Area function.3.142023/12/2205.4.1 虚函数的定义与使用虚函数的定义与使用v为什么把基类中的为什么把基类中的Area函数定义为虚函数时,程序的函数定义为虚函数时,程序的运行结果就正确了呢?这是因为,关键字运行结果就正确了呢?这是因为,关键字“virtual”指示指示C+编译器,函数调用编译器,函数调用“ref.Area()”要在运行时确定所要调用的函数,即要对该调用进要在运行时确定所要调用的函数,即要对该调用进行功
17、能晚绑定。因此,程序在运行时根据引用行功能晚绑定。因此,程序在运行时根据引用ref所所引用的实际对象,调用该对象的成员函数。引用的实际对象,调用该对象的成员函数。2023/12/2215.2 向上类型转换向上类型转换【例例5-3】有一个交通工具有一个交通工具类vehicle,将它作,将它作为基基类派生派生出汽出汽车类motor_ vehicle,再将汽,再将汽车类motor_ vehicle 作作为基基类派生出小汽派生出小汽车类car和卡和卡车类truck,声明声明这些些类并定并定义一个虚函数用来一个虚函数用来显示各示各类信息。程序信息。程序如下:如下:#include using names
18、pace std;class vehicle/基基类vehicle声明声明public:virtual void message()/虚成虚成员函数函数 coutvehicle message endl;private:int wheels;/车轮个数个数 float weight;/车重重;2023/12/2225.2 向上类型转换向上类型转换class motor_vehicle:public vehicle public:void message()cout motor_ vehicle message endl;private:int passengers;/承承载人数人数;class
19、 car:public motor_vehicle public:void message()coutcar message endl;private:float engine;/发动机的机的马力数力数;class truck:public motor_vehicle public:void message()cout truck message message();p=&m;p-message();p=&c;p-message();p=&t;p-message();return 0;2023/12/224vC+规定,如果在派生定,如果在派生类中,没有用中,没有用virtual显式地式地给出虚
20、函数声明,出虚函数声明,这时系系统就会遵循以下就会遵循以下的的规则来判断一个成来判断一个成员函数是不是虚函数:函数是不是虚函数:(1)该函数与基函数与基类的虚函数的虚函数有相同的名称有相同的名称。(2)该函数与基函数与基类的虚函数的虚函数有相同的参数有相同的参数个数及相同的个数及相同的对应参数参数类型型。(3)该函数与基函数与基类的虚函数的虚函数有相同的返回有相同的返回类型或者型或者满足足赋值兼容兼容规则的指的指针、引用型、引用型的返回的返回类型型。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/225说明:明:v(1)通通过定定义虚函数来使用虚函数来使用C+提供的多提供的多态
21、性性机制机制时,派生,派生类应该从它的基从它的基类公用派生。公用派生。之所以有之所以有这个要求,是因个要求,是因为我我们是在是在赋值兼兼容容规则的基的基础上来使用虚函数的,而上来使用虚函数的,而赋值兼兼容容规则成立的前提条件是派生成立的前提条件是派生类从其基从其基类公公用派生。用派生。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/226说明:明:v(2)必必须首先在基首先在基类中定中定义虚函数。由于虚函数。由于“基基类”与与“派生派生类”是相是相对的,因此,的,因此,这项说明并不表明必明并不表明必须在在类等等级的最高的最高层类中声中声明虚函数。在明虚函数。在实际应用中,用中,
22、应该在在类等等级内内需要具有需要具有动态多多态性的几个性的几个层次中的最高次中的最高层类内首先声明虚函数。内首先声明虚函数。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/227说明:明:v(3)在派生在派生类对基基类中声明的虚函数中声明的虚函数进行重新行重新定定义时,关,关键字字virtual可以写也可以不写。可以写也可以不写。但但为了增了增强程序的可程序的可读性,最好在性,最好在对派生派生类的虚函数的虚函数进行重新定行重新定义时也加上关也加上关键字字virtual。v如果在派生如果在派生类中没有中没有对基基类的虚函数重新定的虚函数重新定义,则派生派生类简单地地继承其直接基承
23、其直接基类的虚函的虚函数。数。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/228说明:明:v(4)虽然使用然使用对象名和点运算符的方式也可以象名和点运算符的方式也可以调用虚函数,例如用虚函数,例如语句:句:c.message();可以可以调用虚函数用虚函数car:message()。但是。但是这种种调用是在用是在编译时进行的功能早行的功能早绑定,它没有充定,它没有充分利用虚函数的特性。只有通分利用虚函数的特性。只有通过基基类指指针或引或引用用访问虚函数虚函数时才能才能获得运行得运行时的多的多态性。性。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/229说明
24、:明:v(5)一个虚函数无一个虚函数无论被公用被公用继承多少次,它仍然承多少次,它仍然保持其虚函数的特性。保持其虚函数的特性。v(6)虚函数必虚函数必须是其所在是其所在类的成的成员函数,而不能函数,而不能是友元函数,也不能是静是友元函数,也不能是静态成成员函数,因函数,因为虚虚函数函数调用要靠特定的用要靠特定的对象来决定象来决定该激活哪个函激活哪个函数。但是虚函数可以在另一个数。但是虚函数可以在另一个类中被声明中被声明为友友元函数。元函数。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/230说明:明:v(7)内)内联函数不能是虚函数,因函数不能是虚函数,因为内内联函数函数是不
25、能在运行中是不能在运行中动态确定其位置的。即使虚函确定其位置的。即使虚函数在数在类的内部定的内部定义,编译时仍将其看作是非内仍将其看作是非内联的。的。5.4.1 虚函数的定义与使用虚函数的定义与使用2023/12/231说明:明:v(8)构造函数不能是虚函数。因)构造函数不能是虚函数。因为虚函数作虚函数作为运行运行过程中多程中多态的基的基础,主要是,主要是针对对象的,象的,而构造函数是在而构造函数是在对象象产生之前运行的,因此虚生之前运行的,因此虚构造函数是没有意构造函数是没有意义的。的。v(9)析构函数可以是虚函数,而且通常)析构函数可以是虚函数,而且通常说明明为虚函数。虚函数。5.4.1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向对象程序设计C+ 面向对象程序设计C+课件1第5章 多态性与虚函数 面向 对象 程序设计 课件 多态性 函数