资源预览内容
第1页 / 共32页
第2页 / 共32页
第3页 / 共32页
第4页 / 共32页
第5页 / 共32页
第6页 / 共32页
第7页 / 共32页
第8页 / 共32页
第9页 / 共32页
第10页 / 共32页
第11页 / 共32页
第12页 / 共32页
第13页 / 共32页
第14页 / 共32页
第15页 / 共32页
第16页 / 共32页
第17页 / 共32页
第18页 / 共32页
第19页 / 共32页
第20页 / 共32页
亲,该文档总共32页,到这儿已超出免费预览范围,如果喜欢就下载吧!
点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,第12章 虚函数与多态性,主讲:李政伟,第12章 虚函数与多态性主讲:李政伟,2,第12章 虚函数与多态性,12.1 多态性的概念,12.2 虚函数的定义,12.3 抽象类,12.4 实例研究,2第12章 虚函数与多态性12.1 多态性的概念,3,多态性,是,OOP,的重要特征之一。,多态一词最初来源于希腊语,Polumorphos,,含义是具有多种形式或形态的情形。,多态性,:发出同样的,消息,被不同类型的对象接收时会导致完全不同的行为。,多态性,:父类型具有“引用由它派生的任何子类型”的能力。,多态的实现途径,函数重载,运算符重载,虚函数,12.1 多态性(,polymorphism),的概念,静态多态,动态多态,3多态性是OOP的重要特征之一。12.1 多态性(polym,4,函数重载,:在同一作用域内的多个函数采用相同名字,只要使用不同类型、不同数目的参数。,作为重载函数,:,(,1,)至少在参数个数、参数类型上有所不同。,(,2,)使用缺省函数参数要注意二义性。,如:,void print(int a,int b);,void print(int a,int b,int c=50);,print(10,100);,12.1 多态性(,polymorphism),的概念,4函数重载:在同一作用域内的多个函数采用相同名字,只要使用不,5,12.1 多态性(,polymorphism),的概念,运算符重载,:对已有的运算符赋予多重含义。,必要性,C+,中预定义运算符其运算对象只能是,标准数据类型,,而不适用于,用户自定义类型,(如类)。,实现机制,将指定的运算表达式转化为对,运算符函数,的调用,运算对象转化为运算符函数的,实参,。,512.1 多态性(polymorphism)的概念运算符重,6,分类,系统实现的角度,静态多态性,:在,编译时,系统就能决定调用哪个函数,又称,编译时的多态性,。,函数重载、运算符重载,动态多态性,:在,运行过程中,才动态确定操作所针对的对象。又称,运行时多态,。,虚函数,(,virtual function),12.1 多态性(,polymorphism),的概念,6分类系统实现的角度12.1 多态性(polymorph,7,class,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 非虚函数举例,8,Rectangle: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 i,注意事项,派生类对象指针使用时应注意的问题:,(,1,)声明为指向基类对象的指针可以指向它的公有派生类的对象,但不允许指向它的私有派生类的对象。,(,2,)允许声明为指向基类对象的指针指向它的公有派生类的对象,但不允许将一个声明为指向派生类对象的指针指向基类的对象。,(,3,)声明为指向基类对象的指针,当其指向它的公有派生类的对象时,只能直接访问派生类中从基类继承下来的成员,不能直接访问公有派生类中定义的成员。要想访问其公有派生类中的成员,可将基类指针用显式类型转换方式转换为派生类指针。,注意事项派生类对象指针使用时应注意的问题:,10,12.3 虚函数,12.3.1 虚函数的作用,同一类中,不能,定义,名字,,,参数个数,和,类型,都相同的函数,不能“重复定义,”,。,不同层次中,可以,出现,名字,、,参数个数,和,类型,都相同而功能不同的函数。系统按照,同名覆盖,的原则决定调用对象。,rc1.area(),/,派生类,Rectangle,的成员函数,。,rc1.,Point:,area(),/,基类,Point,的成员函数,P,ref,.area(),1012.3 虚函数12.3.1 虚函数的作用,11,虚函数的声明形式,virtual,(),函数体,成员,函数,,非,static,成员函数,有继承性,基类中定义了虚函数,派生类中,无论是否说明,,同原型函数都自动为虚函数。,作用,:,通过,基类指针或引用调用,执行时根据,指针指向的对象类型动态,决定调用哪个函数,。,12.3 虚函数,11虚函数的声明形式12.3 虚函数,12,class A,public:,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 Avoi,13,虚函数的使用方法,(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()cout,executing Point destructor,endl;,;,class,Circle,:public Point,/,派生类,Circle,类,public:,Circle(),Circle()cout,executing Circle destructor,endl;,private:int radius;,int main(),Point,*p=new,Circle,;,delete p;,executing Point destructor,例12.3 基类中有非虚析构函数时的情况class Poin,17,12.3.4 虚析构函数,用,new,运算符建立对象,且定义了指向基类的指针变量。用带指针参数的,delete,运算符撤销对象时:,只执行,基类,析构函数,而不执行派生类的析构函数,。,1712.3.4 虚析构函数用new运算符建立对象,且定义了,18,virtual,Point()coutexecuting Point destructorendl;,executing Circle destructor,executing Point destructor,例12.3 基类中有非虚析构函数时的情况,基类的析构函数为虚函数时,该基类的所有派生类的,析构函数,都,自动成为虚函数,,即使两者的名字不同。,推荐,:,基类析构函数声明为虚函数,。,18virtual Point()coutexec,19,12.4,纯,虚函数与抽象类,12.4.1 纯虚函数,基类中成员函数设为虚函数,,一般并不是基类本身的要求,,而是考虑到派生类的需要。,基类,Point,没有求面积的,Area,函数,,“,点,”,没有面积,基类本身不需要这个函数。,直接派生类,Circle,和间接派生类,Rectangle,中都需要,Area,函数,且功能不同。,1912.4 纯虚函数与抽象类12.4.1 纯虚函数,20,12.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 are,21,只有函数名字而不具备函数的功能,不能被调用。只是通知编译系统:,这里声明一个虚函数,留待派生类中定义,。,作用,:基类中为其保留了函数名字,以便派生类根据需要对它进行定义。,若基类声明了纯虚函数,而派生类没有定义,则该虚函数在派生类中仍然为纯虚函数。,12.4.1 纯虚函数,21只有函数名字而不具备函数的功能,不能被调用。只是通知编译,22,12.4.2 抽象类(,abstract class),定义,1,:,不能用来定义对象,而只作为基类的类。,定义,2,:,带有,纯虚函数,的类。,一种特殊的类,它为一族类提供统一的操作界面,处于继承层次结构的较上层。,作用,:通过它多态地使用其中的成员函数。,描述了一组子类共同的操作接口,而完整的实现留给了子类。,只能作为基类,,不能实例化,。但可以,声明抽象类的指针和引用,,指向并访问派生类的对象。,若在派生类中对抽象类的所有纯虚函数进行了定义,派生类就成了,具体类,。,若在派生类中没有对所有纯虚函数进行定义,则此派生类仍为,抽象类,。,2212.4.2 抽象类(abstract class)定义,23,例12.4 虚函数和抽象基类的应用,例,12.4,虚函数和抽象基类的应用。,对,Point,为基类的点圆圆柱体类的层次结构进行改写,要求使用
点击显示更多内容>>

最新DOC

最新PPT

最新RAR

收藏 下载该资源
网站客服QQ:3392350380
装配图网版权所有
苏ICP备12009002号-6