欢迎来到装配图网! | 帮助中心 装配图网zhuangpeitu.com!
装配图网
ImageVerifierCode 换一换
首页 装配图网 > 资源分类 > PPT文档下载
 

多态性虚函数运算符重载.ppt

  • 资源ID:12818728       资源大小:1.47MB        全文页数:63页
  • 资源格式: PPT        下载积分:14.9积分
快捷下载 游客一键下载
会员登录下载
微信登录下载
三方登录下载: 微信开放平台登录 支付宝登录   QQ登录   微博登录  
二维码
微信扫一扫登录
下载资源需要14.9积分
邮箱/手机:
温馨提示:
用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
支付方式: 支付宝    微信支付   
验证码:   换一换

 
账号:
密码:
验证码:   换一换
  忘记密码?
    
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

多态性虚函数运算符重载.ppt

第6章多态性和虚函数,6.1多态性6.2虚函数6.3纯虚函数和抽象类6.4虚析构函数,多态性,什么是多态性?同一个消息被不同对象接收时,产生不同的结果。即采用不同方法实现同一接口。,多态性的定义,定义:同一个函数名,实现不同的功能。相同名字函数在不同场合表现出不同行为。调用时,系统根据不同的参数或对象所属的类来调用相应的函数,实现动态的结合。C+支持两种多态性:编译时的多态-通过函数重载和运算符重载来实现。运行时的多态-通过继承和虚函数来实现。,联编,定义:使一个程序经过编译、连接,成为可执行文件的过程。静态联编-在程序运行之前就完成的联编。系统在编译时就知道调用函数的全部信息,函数调用速度快、效率高。动态联编-在程序运行时才能完成的联编。直到程序运行时才能确定调用哪个函数,灵活性、问题抽象性和程序易维护性。,两种多态性,静态联编支持的多态性,称编译时的多态性,通过函数重载和运算符重载来实现。动态联编支持的多态性,称运行时的多态性,通过继承和虚函数来实现,运行时的多态性,通过虚函数和纯虚函数来实现。在基类,定义派生类所拥有的通用接口。例如,在基类中定义名为f()的纯虚函数。在派生类,定义具体的实现方法。所有派生类中都定义了名为f()的虚函数,不同派生类的f()具有不同的功能。实现运行时的多态性。在程序中使用基类指针调用f(),直到程序运行时,系统才能确定调用哪一个函数,基类指针指向哪个派生类,就调用哪个派生类。,6.2虚函数,6.2.1为什么要引入虚函数6.2.2虚函数的定义与使用,6.2.1为什么要引入虚函数,指向基类对象的指针都可以指向它的公有派生类对象,若试图指向它的私有派生类对象是被禁止的。不能将一个声明为指向派生类对象的指针指向其基类的一个对象。指向派生类的指针不能继承。也就是说,基类的指针可以指向它的派生类,但不能再指向它的派生类的派生类。声明为指向基类对象的指针,当它指向公有派生类对象时,只能利用它来直接访问派生类中从基类继承来的成员,不能直接访问公有派生类中特定的成员。若想访问其公有派生类的特定成员,可以将基类指针显式类型转换为派生类指针来实现。,6.2.2虚函数的定义与使用,1虚函数的定义虚函数是引入了派生概念后,用来表现基类和派生类的成员函数之间的一种关系的。虚函数定义是在基类中进行的(virtual),虚函数提供了一种接口界面。在基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新定义。在派生类中重新定义虚函数时,都必须与基类中的原型完全相同。虚函数是一种非静态的成员函数,说明虚函数的方法如下:virtual类型函数名(参数表),6.2.2虚函数的定义与使用,如果在基类中定义了一个虚函数,该虚函数可以在它的一个或多个派生类中重载,不用冠以virtual也自动成为虚函数。,举例,虚函数的使用说明,在基类中,使用关键字virtual。把public和protected部分的成员函数声明为虚函数。在派生类中重新定义虚函数时,函数的返值类型和参数应该同基类中的虚函数完全一致。如果参数不同,属于一般的函数重载,不自动为虚函数。如果仅返值类型不同,产生一个错误,既非重载函数,也非虚函数。,举例,虚函数的使用说明,虚函数的重载函数仍是虚函数。若在基类中声明了一个虚函数,派生类重载该成员函数时无需使用virtual,重载的成员函数自动成为虚函数。若在派生类中没有重新定义虚函数,派生类对象将使用从基类继承的虚函数。虚函数必须是类的成员函数,不能是友元函数,也不能是静态成员函数。析构函数可以是虚函数,但是构造函数不可以是虚函数。,虚函数的使用说明,如果基类中定义了虚函数,使用基类指针调用基类的一个虚函数时,C+系统对该调用进行动态绑定,根据指针当前指向的对象类型,来确定该调用的函数。然而,调用普通函数时,则是静态绑定,编译时就确定该调用的函数。在多重继承下,对虚函数的调用与单一继承的情况相似。(举例),举例,运行时的多态性的作用,运行时的多态性,使得我们可以使用基类指针分别指向多个不同派生类的对象,以此来调用不同功能的函数。,举例,举例,空的虚函数,派生类并不一定必须实现基类中的虚函数,如果派生类想通过虚函数机制存取虚函数,则必须建立一条从基类到派生类的虚函数路径。许多没有使用虚函数的中间类也必须声明该函数,以保证其后的派生类能使用该虚函数。可以通过声明空函数来达到此目的。,空的虚函数(举例),#includeclassBasepublic:virtualvoidprint()cout<<“classbase!n”;classSon:publicbasepublic:virtualvoidprint();classGrandson:publicsonpublic:virtualvoidprint()cout<print();voidmain()base*pbase=newbase;son*pson=newson;grandson*pgrandson=newgrandson;show(pbase);show(pson);show(pgrandson);,classbase!classgrandson!,空的虚函数(举例),可以考虑:如果去掉son类的空虚函数,程序运行结果如何?如果去掉virtual关键字,程序运行结果又如何?如果保留son类的空虚函数,去掉grandson类的虚函数定义,程序运行结果又如何?如果把son类的虚函数定义为cout<<“classson!n”,之后去掉grandson类的虚函数定义,程序的运行结果又如何?,6.3.1纯虚函数的概念,有时,基类仅表示一种抽象的概念,并不与具体的事务相联系。于是,在基类中说明的虚函数只是为了给它的派生类提供一个公共的界面。这样虚函数在基类中没定义,也没有函数体。在派生类中需要根据具体情况来定义重载虚函数的功能。在这种情况下,可以将基类中的虚函数定义成纯虚函数。纯虚函数是一种没有具体实现的特殊的虚函数。一个基类中有一个纯虚函数时,则在它的派生类中至少有一个虚函数,否则纯虚函数是无意义的。,6.3.1纯虚函数的概念,纯虚函数的定义格式如下:virtual类型(函数名)(参数表)=0;“=0”不表示函数返回值为0,只起形式上的作用,告之系统这是“纯虚函数”。由于纯虚函数所在的类中没有它的定义,不具备函数的功能,在该类的构造函数、析构函数及其它函数中不允许调用纯虚函数,否则会导致程序运行错误。作用:在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行重新定义。,6.3.1纯虚函数的概念(举例),#includeUsingnamespacestd;classCircle/声明基类Circlepublic:voidsetr(intx)r=x;virtualvoidshow()=0;/定义纯虚函数protected:intr;ClassArea:publicCirclepublic:voidshow()/重定义虚函数,求圆面积cout<<“Areais”<<3.14*r*r<<endl;,Classperimeter:publicCirclepublic:voidshow()/重定义虚函数,求圆周长coutshow();ptr=,6.3.2抽象类的概念,1抽象类和具体类的概念如果一个类至少有一个纯虚函数,那么就称该类为抽象类。能够建立实例化对象的类称为具体类,也就是不含纯虚函数的类为具体类。抽象类的主要作用是为其所组织的继承层次结构提供一个公共的基类,它刻划了公有行为的特征,其它类可以从它这里继承和实现接口,纯虚函数的实现由其具体的派生类来提供。,抽象类的使用说明,抽象类只能作为其它类的基类,不能创建对象实例,因为含有一个或多个未定义的函数。抽象类不能用作参数类型,函数返回类型,或者显式转换的类型。可以声明指向抽象类的指针或引用,使用此指针并指向它的派生类,以支持运行时的多态性。在派生类中必须重载基类的纯虚函数,即给出有函数体的定义,否则,派生类仍被看作一个抽象类。,抽象类的使用举例,2抽象类举例(计算各类形状的总面积),#includeclassshape/抽象类的定义public:virtualfloatarea()=0;classtriangle:publicshape/三角形类protected:floath,w;public:triangle(floathh,floatww)h=hh;w=ww;floatarea()returnh*w*0.5;,3抽象类举例(计算各类形状的总面积),classrectangle:publictriangle/矩形类public:rectangle(floath,floatw):triangle(h,w)floatarea()returnh*w;classcircle:publicshape/圆类private:floatradius;public:circle(floatr)radius=r;floatarea()returnradius*radius*3.14;,3抽象类举例(计算各类形状的总面积),floattotal(shape*s,intn)/求所有图形的总面积floatsum=0;for(inti=0;iarea();returnsum;voidmain()shape*s4;/指针数组s0=newtriangle(3,4);s1=newrectangle(2,4);s2=newcircle(5);s3=newcircle(8);floatsum=total(s,4);cout<<sum<<endl;,End.,6.4虚析构函数,将析构函数设计为虚函数不是必须的,只有在栈中动态创建的对象时(new),指针是指向基类的,当我们要释放动态对象时(delete),要把基类中的析构函数设计为虚函数。这时的基类和派生类的析构函数都应该为虚函数。因为析构函数执行时首先调用派生类的析构函数,其次才调用基类的析构函数,如果析构函数不是虚函数,而程序执行时又要通过基类的指针去销毁派生类的动态对象,那么用delete销毁对象时,只调用了基类的析构函数,会造成销毁对象不完全。,6.4虚析构函数,#includeclassbasepublic:base()cout<<"base()"<<endl;classsub:publicbasepublic:sub()cout<<"subclass()"<、new、delete。(2)单目运算符最好重载为成员函数。(3)对于复合的赋值运算符如+=、-=、*=、/=、/函数体注意友元函数不属于任何类,它没有this指针,这与成员函数完全不同。若运算符是一元的,则参数表中有一个操作数;若运算符是二元的,则参数表中有两个操作数。也就是说在用友元定义重载运算符时,所有的操作数均需要用参数来传递。friendToperator(Ta,Tb);,7.3运算符重载为友元函数,例如对于两个Complex类的对象相加的函数:ComplexAdd(Complex/用重载运算符“+”编译器遇到语句c3=c1+c2时,会把它替换成c3=operator+(c1,c2)的完整形式,即与重载的运算符函数原形相匹配。,7.3运算符重载为友元函数,这种运算符重载函数也称为双目友元运算符重载函数。双目运算符有两个操作数,通常在运算符的左右两侧(加减乘除)。当用友元函数重载双目运算符时,两个操作数都要传给运算符重载函数。在C+中,不能直接进行复数加、减、乘、除运算,介我们可以定义四个友元运算符函数,通过重载+、-、*、/运算符来实现复数运算。,classComplex/复数类private:doubleimage;doublereal;public:Complex(doublex=0.0,doubley=0.0)/构造函数real=x;image=y;voidPrint();friendComplexoperator+(constComplex/以复数格式输出,Complexoperator+(constComplex,6+9i,7.3运算符重载为友元函数,还有一种运算符重载函数称为单目友元运算符重载函数。单目运算符只有一个操作数,通常在运算符的右侧(+、-、-、!)。,classCoordpublic:coord(inti=0,intj=0);voiddisplay();friendCoordoperator+(Coord,VoidCoord:display()cout<<“x:”<<x<<“,y:”<<y<<endl;Coordoperator+(Coord,X:11,y:22X:12,y:23X:13,y:24,7.4运算符重载为成员函数,在上面的程序代码中,运算符“+”的重载函数被定义在Complex类之外,作为该类的友元函数,能访问类中的私有数据成员real和image,但是这种友元函数与类配合的情况,降低了该类独立性,破坏了该类的封装特性。因此在一般情况下,应将类所涉及的所有操作都定义在类中,即应将类的运算符重载成类中的成员函数。因为是在类中定义的操作,操作的一方就是当前的对象,成员变量也可以自由访问,这样,如果是重载双目运算符,就只要设置一个参数作为右侧运算量,而左侧运算量就是该对象本身;如果是重载单目运算符,就不必另外设置参数,运算符的操作量就是对象本身。,7.4运算符重载为成员函数,返回值类型operator运算符(形参表)若运算符是一元的,则参数表为空,此时当前对象作为此运算符的单操作数;若运算符是二元的,则参数表中有一个操作数,此时当前对象作为此运算符的左操作数,参数表中的操作数作为此运算符的右操作数,依此类推。运算符函数的定义方式同一般成员函数,对类成员的访问与一般成员函数相同,定义如下:type类名:operator(参数表)/函数体重载运算符的使用方法同原运算符一样,只是它的操作数一定要是定义它的特定类的对象。,/*07_04.cpp*/#includeclassComplex/复数类private:doublereal,image;public:Complex(doublex=0.0,doubley=0.0)/构造函数real=x;image=y;Complexoperator-(constComplex/以复数格式输出,ComplexComplex:operator-(constComplex/返回对象的引用,intmain()Complexc1(2,7),c2(4,2),c3;c3=c1-c2;/表达式的完整形式应该是c3=c1.operator-(c2)c3.Print();if(c3=c1)cout<<”c3equalstoc1”<<endl;/判断c3和c1是否相等elsecout<<”c3doesntequaletoc1”<<endl;c3=-c2;/把c3赋值为c2的求负取反值c3.Print();c3+=c2;c3.Print();return0;,-2+5ic3doesntequaletoc1-4+-2i0+0i,在以上main()函数中,编译器重新解释后,四个运算符重载对应的完整形式分别是:c1-c2等价于c1.operator(c2)c3=c1等价于c3.operator=(c1)-c2等价于c2.operator-();c3+=c2等价于c3.operator+=(c2);由此可以看出,针对双目运算符被重载为类的成员函数,实质是运算符左侧的对象调用了自身的运算符函数,右侧的操作量作为运算符函数的参数,因此要求运算符左侧的操作量必须是类的对象。,7.4运算符重载为成员函数,7.5几个常用运算符的重载,1自增和自减运算符的重载前自增运算符+和后自增运算符+重载的语法operator+();/前operator+(int);/后【例7.5】用成员函数重载前自增和后自增运算符。通过例子可以看出,重载后置自增运算符,多了一个int型的参数(不带参数名),这个参数只是为了与前置自增运算符重载函数有所区别,此外没任何作用。C+编译系统在遇到后置自增运算符时,会自动调用此函数,参数int一般被传递给值0。例如,p1+就相当于函数调用p1.operator+(0)。,/*07_05.cpp*/#includeclassPoint/复数类private:intx,y;public:Point(inti=0,intj=0)/构造函数x=i;y=j;voidShow()/显示点值,格式:(x,y)cout<<”(”<<x<<”,”<<y<<”)”<3.为Date类重载“+”运算符,实现在某一个日期(月、日、年)上加一个天数。如输入2000.2.15,加个365天,结果是2001.2.14。注意:需要考虑每个月不同天数及闰年问题。,

注意事项

本文(多态性虚函数运算符重载.ppt)为本站会员(tian****1990)主动上传,装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知装配图网(点击联系客服),我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

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

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


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