C++程序设计基础第12章-虚函数与多态性课件

上传人:494895****12427 文档编号:241293923 上传时间:2024-06-15 格式:PPTX 页数:32 大小:366.83KB
返回 下载 相关 举报
C++程序设计基础第12章-虚函数与多态性课件_第1页
第1页 / 共32页
C++程序设计基础第12章-虚函数与多态性课件_第2页
第2页 / 共32页
C++程序设计基础第12章-虚函数与多态性课件_第3页
第3页 / 共32页
点击查看更多>>
资源描述
第第12章章 虚函数与多态性虚函数与多态性主讲:李政伟主讲:李政伟第12章 虚函数与多态性主讲:李政伟2第第12章章 虚函数与多态性虚函数与多态性12.1 多多态态性的概念性的概念12.2 虚函数的定虚函数的定义义12.3 抽象抽象类类12.4 实实例研究例研究2第12章 虚函数与多态性12.1 多态性的概念3多态性多态性是是是是OOPOOP的重要特征之一。的重要特征之一。的重要特征之一。的重要特征之一。多多态一一词最初来源于希腊最初来源于希腊语Polumorphos,含,含义是具是具有多种形式或形有多种形式或形态的情形。的情形。多态性多态性:发出同出同样的的消息消息被不同被不同类型的型的对象接收象接收时会会导致完全不同的行致完全不同的行为。多态性多态性:父:父类型具有型具有“引用由它派生的任何子引用由它派生的任何子类型型”的能力。的能力。多态的实现途径多态的实现途径函数重函数重函数重函数重载载运算符重运算符重运算符重运算符重载载虚函数虚函数虚函数虚函数12.1 多态性多态性(polymorphism)的概念的概念静态多态静态多态动态多态动态多态3多态性是OOP的重要特征之一。12.1 多态性(polym4函数重载函数重载:在同一作用域内的多个函数采用相:在同一作用域内的多个函数采用相同名字,只要使用不同同名字,只要使用不同类型、不同数目的参数。型、不同数目的参数。作为重载函数作为重载函数:(1)至少在参数个数、参数)至少在参数个数、参数类型上有所不同。型上有所不同。(2)使用缺省函数参数要注意二)使用缺省函数参数要注意二义性。性。如:如:void print(int a,int b);void print(int a,int b,int c=50);print(10,100);12.1 多态性多态性(polymorphism)的概念的概念4函数重载:在同一作用域内的多个函数采用相同名字,只要使用不512.1 多态性多态性(polymorphism)的概念的概念运算符重载运算符重载:对已有的运算符已有的运算符赋予多重含予多重含义。必要性必要性&C+中中预定定义运算符其运算运算符其运算对象只能是象只能是标准数据准数据类型型,而不适用于,而不适用于用用户自定自定义类型型(如(如类)。)。实现机制实现机制&将指定的运算表达式将指定的运算表达式转化化为对运算符函数运算符函数的的调用,运算用,运算对象象转化化为运算符函数的运算符函数的实参参。512.1 多态性(polymorphism)的概念运算符重6分类分类系统实现的角度系统实现的角度&静态多态性静态多态性:在:在编译时编译时系系统就能决定就能决定调用用哪个函数,又称哪个函数,又称编译时的多态性编译时的多态性。函数重函数重载、运算符重、运算符重载&动态多态性动态多态性:在:在运行过程中运行过程中才才动态确定操确定操作所作所针对的的对象。又称象。又称运行时多态运行时多态。虚函数虚函数(virtual function)12.1 多态性多态性(polymorphism)的概念的概念6分类系统实现的角度12.1 多态性(polymorph7class Point public:Point(double i,double j)x=i;y=j;double Area()const return 0.0;private:double x,y;class Rectangle:public Point public:Rectangle(double i,double j,double k,double l);double Area()const return w*h;private:double w,h;例例12.1 非虚函数举例非虚函数举例7class Point例12.1 非虚函数举例8Rectangle:Rectangle(double i,double j,double k,double l):Point(i,j)w=k;h=l;void fun(Point&Pref)coutArea=Pref.Area()endl;void main()Rectangle rec(3.0,6.0,15.0,20.0);fun(rec);例例12.1非虚函数举例非虚函数举例8Rectangle:Rectangle(double i1012.3 虚函数虚函数12.3.1 虚函数的作用虚函数的作用同一同一类中中不能不能定定义名字名字,参数个数参数个数和和类型类型都相都相同的函数,不能同的函数,不能“重复定重复定义”。不同不同层次中次中可以可以出出现名字名字、参数个数参数个数和和类型类型都都相同而功能不同的函数。系相同而功能不同的函数。系统按照按照同名覆盖同名覆盖的的原原则决定决定调用用对象。象。rc1.area()/派生派生类Rectangle的成的成员函数函数。rc1.Point:area()/基基类Point的成的成员函数函数Pref.area()1012.3 虚函数12.3.1 虚函数的作用11虚函数的声明形式虚函数的声明形式virtual ()函数体函数体&成员成员函数,函数,非非static成成员函数函数&有有继承性,基承性,基类中定中定义了虚函数,派生了虚函数,派生类中中无无无无论论是否是否是否是否说说明明明明,同原型函数都自,同原型函数都自动为虚函数。虚函数。&作用作用:通通通通过过基基基基类类指指指指针针或引用或引用或引用或引用调调用用用用执执行行行行时时根据根据根据根据指指指指针针指向的指向的指向的指向的对对象象象象类类型型型型动态动态决定决定决定决定调调用哪个函数用哪个函数用哪个函数用哪个函数。12.3 虚函数虚函数11虚函数的声明形式12.3 虚函数12class Apublic:virtual void display()cout“A:display();class B:public A public:void display()/自动成为虚函数自动成为虚函数 cout“B:display();class C:public B public:void display()/自动成为虚函数自动成为虚函数 cout“C:display()display();void main()A a1,*p;B b1;C c1;p=&a1;fun(p);p=&b1;fun(p);p=&c1;fun(p);12class Aclass B:public Avoi13虚函数的使用方法虚函数的使用方法(1)基基类中用中用virtual声明其声明其为虚函数虚函数(2)要求要求函数名函数名、返回类型返回类型、参数个数参数个数和和类类型型全部与基全部与基类的虚函数相同,根据需要重新的虚函数相同,根据需要重新定定义函数体。函数体。(3)定定义一个一个指向基类对象的指针变量指向基类对象的指针变量,使,使它指向同一它指向同一类族中要族中要调用用该函数的函数的对象。象。(4)通过该指针变量调用此虚函数通过该指针变量调用此虚函数,调用的是用的是指指针变量指向的量指向的对象所属象所属类的同名函数。的同名函数。例例12.2 基类与派生类中有同名函数基类与派生类中有同名函数13虚函数的使用方法 例12.2 基类与派生类中有同名函数14函数重载函数重载可用于普通函数和可用于普通函数和类的成的成员函数;函数;虚函数虚函数只能用于只能用于类的成的成员函数。函数。函数重载函数重载可用于构造函数;可用于构造函数;虚函数虚函数不可以。不可以。重载成员函数重载成员函数必必须属于同一个属于同一个类,为横向;横向;虚函数虚函数是同一是同一类族中基族中基类和派生和派生类的的同同原型原型函数,函数,为纵向。向。函数重载函数重载要求函数名字相同,但参数个数或要求函数名字相同,但参数个数或类型不型不同;同;虚函数虚函数要求同一要求同一类族所有虚函数的名字、参数族所有虚函数的名字、参数类型、个数完全相同。型、个数完全相同。函数重载函数重载在在编译时确定;确定;虚函数虚函数在程序运行在程序运行时确定。确定。函数重载函数重载 PK 虚函数虚函数14函数重载可用于普通函数和类的成员函数;虚函数只能用于类的12.2.3 虚函数的限制虚函数的限制使用虚函数使用虚函数时应注意如下注意如下问题:(1)虚函数声明只能出)虚函数声明只能出现在在类声明的函数原型的声明声明的函数原型的声明中,不能出中,不能出现在函数体在函数体实现中,同中,同时基基类中只有保中只有保护成成员或公有成或公有成员才能被声明才能被声明为虚函数。虚函数。(2)派生)派生类中重新定中重新定义虚函数虚函数时,关,关键字字virtual可以写可以写也可不写,也可不写,为避免引起混乱,避免引起混乱,应写上写上该关关键字。字。(3)动态联编只能通只能通过成成员函数来函数来调用或通用或通过指指针、引用来引用来访问虚函数,如果用虚函数,如果用对象名的形式来象名的形式来访问虚函虚函数,将采用静数,将采用静态联编。(4)构造函数不能声明)构造函数不能声明为虚函数,析构函数可以声明虚函数,析构函数可以声明为虚函数虚函数12.2.3 虚函数的限制使用虚函数时应注意如下问题:例例12.3 基类中有非虚析构函数时的情况基类中有非虚析构函数时的情况class Point /基基类Point类 public:Point()Point()coutexecuting Point destructorendl;class Circle:public Point /派生派生类Circle类public:Circle()Circle()coutexecuting Circle destructorendl;private:int radius;int main()Point*p=new Circle;delete p;executing Point destructor例12.3 基类中有非虚析构函数时的情况class Poin1712.3.4 虚析构函数虚析构函数用用new运算符建立运算符建立对象,且定象,且定义了指向基了指向基类的指的指针变量。用量。用带指指针参数的参数的delete运运算符撤算符撤销对象象时:只执行只执行基类基类析构函数,析构函数,而不执行派生类的析构函数而不执行派生类的析构函数。1712.3.4 虚析构函数用new运算符建立对象,且定义了18virtual Point()coutexecuting Point destructorendl;executing Circle destructorexecuting Point destructor例例12.3 基类中有非虚析构函数时的情况基类中有非虚析构函数时的情况基类的析构函数为虚函数时,该基类的所基类的析构函数为虚函数时,该基类的所有派生类的有派生类的析构函数析构函数都都自动成为虚函数自动成为虚函数,即使两者的名字不同。即使两者的名字不同。推荐推荐:基类析构函数声明为虚函数基类析构函数声明为虚函数。18virtual Point()coutexec1912.4 纯纯虚函数与抽象类虚函数与抽象类12.4.1 纯虚函数纯虚函数基基类中成中成员函数函数设为虚函数,虚函数,一般并不是基类一般并不是基类本身的要求本身的要求,而是考,而是考虑到派生到派生类的需要。的需要。基基类Point没有求面没有求面积的的Area函数,函数,“点点”没有面没有面积,基,基类本身不需要本身不需要这个函数。个函数。直接派生直接派生类Circle和和间接派生接派生类Rectangle中都中都需要需要Area函数,且功能不同。函数,且功能不同。1912.4 纯虚函数与抽象类12.4.1 纯虚函数2012.4.1 纯虚函数纯虚函数virtual float area()const return 0;/虚函数虚函数virtual float area()const=0;/纯虚函数虚函数纯虚函数纯虚函数(pure virtual function):在声明虚函数:在声明虚函数时被被“初始化初始化”为0的函数。的函数。纯虚函数的声明格式:纯虚函数的声明格式:virtual 函数类型函数类型 函数名函数名(参数表列参数表列)=0;注注:无函数体;无函数体;“=0”不表示返回不表示返回值为0,只用,只用来告知是来告知是纯虚函数虚函数;以分号以分号结束。束。2012.4.1 纯虚函数virtual float are21只有函数名字而不具只有函数名字而不具备函数的功能,不能被函数的功能,不能被调用。只是通知用。只是通知编译系系统:这里声明一个虚函这里声明一个虚函数,留待派生类中定义数,留待派生类中定义。作用作用:基:基类中中为其保留了函数名字,以便派生其保留了函数名字,以便派生类根据需要根据需要对它它进行定行定义。若基若基类声明了声明了纯虚函数,而派生虚函数,而派生类没有定没有定义,则该虚函数在派生虚函数在派生类中仍然中仍然为纯虚函数。虚函数。12.4.1 纯虚函数纯虚函数21只有函数名字而不具备函数的功能,不能被调用。只是通知编译2212.4.2 抽象类抽象类(abstract class)定义定义1:不能用来定义对象不能用来定义对象而只作而只作为基基类的的类。定义定义2:带有有纯虚函数纯虚函数的的类。一种特殊的一种特殊的一种特殊的一种特殊的类类,它,它,它,它为为一族一族一族一族类类提供提供提供提供统统一的操作界面,一的操作界面,一的操作界面,一的操作界面,处处于于于于继继承承承承层层次次次次结结构的构的构的构的较较上上上上层层。作用作用:通:通:通:通过过它多它多它多它多态态地使用其中的成地使用其中的成地使用其中的成地使用其中的成员员函数。函数。函数。函数。描述了一描述了一描述了一描述了一组组子子子子类类共同的操作接口,而完整的共同的操作接口,而完整的共同的操作接口,而完整的共同的操作接口,而完整的实现实现留留留留给给了子了子了子了子类类。只能作只能作只能作只能作为为基基基基类类,不能不能不能不能实实例化例化例化例化。但可以。但可以。但可以。但可以声明抽象声明抽象声明抽象声明抽象类类的指的指的指的指针针和引用和引用和引用和引用,指向并,指向并,指向并,指向并访问访问派生派生派生派生类类的的的的对对象。象。象。象。若在派生若在派生类中中对抽象抽象类的所有的所有纯虚函数虚函数进行了定行了定义,派生派生类就成了就成了具体类具体类。若在派生若在派生类中没有中没有对所有所有纯虚虚函数函数进行定行定义,则此派生此派生类仍仍为抽象类抽象类。2212.4.2 抽象类(abstract class)定义23例例12.4 虚函数和抽象基类的应用虚函数和抽象基类的应用例例12.4 虚函数和抽象基类的应用。虚函数和抽象基类的应用。对Point为基基类的点的点圆圆柱体柱体类的的层次次结构构进行改写,要求使用虚函数和抽象基行改写,要求使用虚函数和抽象基类。顶层是抽象基是抽象基类Shape(形状形状)。Point(点点),Circle(圆),Cylinder(圆柱体柱体)都是都是Shape类的直接派的直接派生生类和和间接派生接派生类。23例12.4 虚函数和抽象基类的应用例12.4 虚函数和抽24第第(1)部分部分class Shape/抽象基抽象基类Shapepublic:virtual float area()const return 0.0;virtual float volume()const return 0.0;virtual void shapeName()const=0;24第(1)部分class Shape/抽象基类Shap25第第(2)部分部分class Point:public Shape/Shape的公用派生的公用派生类public:Point(float=0,float=0);void setPoint(float,float);float getX()const return x;float getY()const return y;virtual void shapeName()const coutPoint:;friend ostream&operator(ostream&,const Point&);protected:float x,y;25第(2)部分class Point:public Sh26class Circle:public Point /Circle类public:Circle(float x=0,float y=0,float r=0);void setRadius(float);float getRadius()const;virtual float area()const;virtual void shapeName()const coutCircle:;friend ostream&operator(ostream&,const Circle&);protected:float radius;第第(3)部分部分26class Circle:public Point /28第第(4)部分部分class Cylinder:public Circle/Cylinder类public:Cylinder(float x=0,float y=0,float r=0,float h=0);void setHeight(float);virtual float area()const;virtual float volume()const;virtual void shapeName()const coutCylinder:;friend ostream&operator(ostream&,const Cylinder&);protected:float height;28第(4)部分class Cylinder:public 29Cylinder:Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h)float Cylinder:area()const return 2*Circle:area()+2*3.14159*radius*height;float Cylinder:volume()const return Circle:area()*height;ostream&operator(ostream&output,const Cylinder&cy)outputcy.x,cy.y,r=cy.radius,h=cy.height;return output;第第(4)部分部分29Cylinder:Cylinder(float a,f30int main()Point point(3.2,4.5);Circle circle(2.4,1.2,5.6);Cylinder cylinder(3.5,6.4,5.2,10.5);point.shapeName();coutpointendl;circle.shapeName();coutcircleendl;cylinder.shapeName();coutcylinderendlshapeName();coutx=point.getX(),y=point.getY()narea=area()nvolume=volume()shapeName();/动态关关联 coutx=circle.getX(),y=circle.getY()narea=area()nvolume=volume()shapeName();/动态关关联coutx=cylinder.getX(),y=cylinder.getY()narea=area()nvolume=volume()nn;return 0;第第(5)部分部分31pt=&circle;/指针指向Circle类对象32Thank YouThe End of Ch.12.32Thank YouThe End of Ch.12.
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 教学培训


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!