西安工业大学耿军雪老师的C课件之多态性.ppt

上传人:汽*** 文档编号:568548614 上传时间:2024-07-25 格式:PPT 页数:95 大小:692.50KB
返回 下载 相关 举报
西安工业大学耿军雪老师的C课件之多态性.ppt_第1页
第1页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第2页
第2页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第3页
第3页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第4页
第4页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第5页
第5页 / 共95页
点击查看更多>>
资源描述

《西安工业大学耿军雪老师的C课件之多态性.ppt》由会员分享,可在线阅读,更多相关《西安工业大学耿军雪老师的C课件之多态性.ppt(95页珍藏版)》请在金锄头文库上搜索。

1、面向对象技术与C+计算机学院Object Oriented5-0分析结果分析结果?#includeclasspoint doublex,y;public:point(doublei,doublej)x=i;y=j;doublearea()return0.0;classrectangle:publicpoint doublew,h;public:rectangle(doublei,doublej,doublem,doublen):point(i,j)w=m;h=n;doublearea()returnw*h;voidfun(point&s)couts.area()endl;voidmain()

2、rectanglerec(3.0,5.0,15.0,25.0);fun(rec);Object Oriented第五章第五章多态性多态性本章本章本章本章主要内容:主要内容:主要内容:主要内容:u多态性多态性多态性多态性 同一名称,不同的功能实现方式同一名称,不同的功能实现方式同一名称,不同的功能实现方式同一名称,不同的功能实现方式 u运算符重载运算符重载运算符重载运算符重载 多态的经典内容多态的经典内容多态的经典内容多态的经典内容 u虚函数虚函数虚函数虚函数 动态绑定动态绑定动态绑定动态绑定 u纯虚函数纯虚函数纯虚函数纯虚函数 统一接口统一接口统一接口统一接口 u抽象类抽象类抽象类抽象类 定义

3、一个框架,由其衍生对象完善定义一个框架,由其衍生对象完善定义一个框架,由其衍生对象完善定义一个框架,由其衍生对象完善Object Oriented一、多态性一、多态性多态性:是指不同对象在收到相同的消息时,产生多态性:是指不同对象在收到相同的消息时,产生多态性:是指不同对象在收到相同的消息时,产生多态性:是指不同对象在收到相同的消息时,产生不同的动作不同的动作不同的动作不同的动作用同一个名字定义不同的函数,执用同一个名字定义不同的函数,执用同一个名字定义不同的函数,执用同一个名字定义不同的函数,执行不同但相似的操作行不同但相似的操作行不同但相似的操作行不同但相似的操作实现实现实现实现“ “一个

4、接口,多种方一个接口,多种方一个接口,多种方一个接口,多种方法法法法” ”。u多态的实现:多态的实现: u函数重载:函数重载:通过形参来区分通过形参来区分通过形参来区分通过形参来区分 u运算符重载:运算符重载:只是一种只是一种只是一种只是一种“语法修饰语法修饰语法修饰语法修饰”,是专用格式的函数重,是专用格式的函数重,是专用格式的函数重,是专用格式的函数重载载载载 u虚函数:虚函数:冠以关键字冠以关键字冠以关键字冠以关键字 virtual virtual virtual virtual 的成员函数称为虚函数的成员函数称为虚函数的成员函数称为虚函数的成员函数称为虚函数Object Oriente

5、d二、联编的概念及分类二、联编的概念及分类二、联编的概念及分类二、联编的概念及分类1 1、联编的概念、联编的概念、联编的概念、联编的概念联联联联编编编编:源源源源程程程程序序序序经经经经过过过过编编编编译译译译、联联联联接接接接成成成成可可可可执执执执行行行行文文文文件件件件的的的的过过过过程程程程 即将可执行代码联编(装配)在一起的过程。即将可执行代码联编(装配)在一起的过程。即将可执行代码联编(装配)在一起的过程。即将可执行代码联编(装配)在一起的过程。2 2、联编的分类:、联编的分类:、联编的分类:、联编的分类: 静静静静态态态态联联联联编编编编(前前前前期期期期联联联联编编编编):在在

6、在在运运运运行行行行前前前前完完完完成成成成的的的的联联联联编编编编在在在在编编编编译译译译时时时时完完完完成成成成(要要要要求求求求在在在在编编编编译译译译时时时时就就就就知知知知道道道道调调调调用用用用函函函函数数数数的的的的全全全全部部部部信信信信息息息息)其优点是其优点是其优点是其优点是“ “效率高效率高效率高效率高” ”。( ( ( (重载函数使用静态联编。重载函数使用静态联编。重载函数使用静态联编。重载函数使用静态联编。) ) ) )动动动动态态态态联联联联编编编编(后后后后期期期期联联联联编编编编):在在在在运运运运行行行行时时时时才才才才完完完完成成成成的的的的联联联联编编编编

7、在在在在程程程程序序序序运运运运行行行行时时时时动动动动态态态态调调调调用用用用所所所所需需需需函函函函数数数数优优优优点点点点是是是是提提提提供供供供了了了了更更更更好好好好的的的的“ “灵灵灵灵活活活活性性性性” ”、问问问问题题题题的的的的“ “抽抽抽抽象象象象性性性性” ”、程程程程序序序序的的的的“ “易易易易维维维维护性护性护性护性” ”。(switch (switch (switch (switch 语句和语句和语句和语句和 if if if if 语句是动态联编的例子语句是动态联编的例子语句是动态联编的例子语句是动态联编的例子) ) ) )Object Oriented三、多态

8、性的分类三、多态性的分类 编编编编译译译译时时时时多多多多态态态态性性性性:静静静静态态态态联联联联编编编编支支支支持持持持的的的的多多多多态态态态性性性性(静静静静态态态态多多多多态态态态性性性性)通过函数重载及运算符重载实现。通过函数重载及运算符重载实现。通过函数重载及运算符重载实现。通过函数重载及运算符重载实现。 运运运运行行行行时时时时多多多多态态态态性性性性:动动动动态态态态联联联联编编编编支支支支持持持持的的的的多多多多态态态态性性性性(动动动动态态态态多多多多态态态态性性性性)通过虚函数实现。通过虚函数实现。通过虚函数实现。通过虚函数实现。 四、函数重载四、函数重载同同同同一一一

9、一个个个个类类类类中中中中的的的的同同同同名名名名函函函函数数数数参参参参数数数数个个个个数数数数不不不不一一一一样样样样、参参参参数数数数类类类类型不一样、参数个数及类型不一样;型不一样、参数个数及类型不一样;型不一样、参数个数及类型不一样;型不一样、参数个数及类型不一样;不不不不同同同同类类类类中中中中的的的的同同同同名名名名函函函函数数数数通通通通过过过过类类类类名名名名调调调调用用用用或或或或类类类类的的的的对对对对象象象象调调调调用。用。用。用。 同同同同一一一一个个个个类类类类中中中中同同同同名名名名的的的的普普普普通通通通成成成成员员员员函函函函数数数数及及及及常常常常量量量量成

10、成成成员员员员函函函函数数数数通过通过通过通过constconst实现重载。实现重载。实现重载。实现重载。例如:例如:Show ( int , char ) ;Show ( char * , float ) ;例如:例如:A : Show ( );有别于B : Show ( );例如:例如:Aobj . Show ( )调用A : Show ( )Bobj . Show ( )调用B : Show ( )Object Oriented第一节第一节虚函数和基类指针虚函数和基类指针 冠以关键字冠以关键字冠以关键字冠以关键字 virtualvirtual的成员函数称为虚函数的成员函数称为虚函数的成员

11、函数称为虚函数的成员函数称为虚函数 实现运行时多态的关键首先是要说明虚函数,另外,实现运行时多态的关键首先是要说明虚函数,另外,实现运行时多态的关键首先是要说明虚函数,另外,实现运行时多态的关键首先是要说明虚函数,另外,必须用基类指针调用派生类的不同实现版本必须用基类指针调用派生类的不同实现版本必须用基类指针调用派生类的不同实现版本必须用基类指针调用派生类的不同实现版本 虚函数与派生类相结合,使虚函数与派生类相结合,使虚函数与派生类相结合,使虚函数与派生类相结合,使C+C+能支持运行时多态性能支持运行时多态性能支持运行时多态性能支持运行时多态性实现在基类中定义派生类所拥有的通用实现在基类中定义

12、派生类所拥有的通用实现在基类中定义派生类所拥有的通用实现在基类中定义派生类所拥有的通用“ “接口接口接口接口” ”,而在派生类中定义具体的实现方法,即,而在派生类中定义具体的实现方法,即,而在派生类中定义具体的实现方法,即,而在派生类中定义具体的实现方法,即“ “一个接口,一个接口,一个接口,一个接口,多种方法多种方法多种方法多种方法” ”。Object Oriented5-1#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charx;classFirst_d:publicBasepubl

13、ic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:chary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_

14、objS_obj通过基类指针通过基类指针只能访问从基类继承的成员只能访问从基类继承的成员 Object Oriented5-2#includeclassBasepublic:Base(charxx)x=xx;virtualvoidwho()coutBaseclass:xn;protected:charx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:chary;classSecond_d:publicFirst_dpu

15、blic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_obj由于由于who()who()的虚特性的虚特性随着随着p p指向不同对象,执行不同实现版本指向不同对象,执行不同实现版本 Object Oriented注意:注意:注意:注意: 一个虚函数,在派生类层界面相同的重载函数都保持一个虚函数,在派生类层界面相同的重载函数都保持一个虚函数,在派生类

16、层界面相同的重载函数都保持一个虚函数,在派生类层界面相同的重载函数都保持虚特性虚特性虚特性虚特性 虚函数必须是虚函数必须是虚函数必须是虚函数必须是类的成员函数类的成员函数类的成员函数类的成员函数,不能是全局函数和静态,不能是全局函数和静态,不能是全局函数和静态,不能是全局函数和静态函数函数函数函数 不能将友员说明为虚函数,但虚函数可以是另一个类不能将友员说明为虚函数,但虚函数可以是另一个类不能将友员说明为虚函数,但虚函数可以是另一个类不能将友员说明为虚函数,但虚函数可以是另一个类的友员的友员的友员的友员 析构函数可以是虚函数,但构造函数不能是虚函数析构函数可以是虚函数,但构造函数不能是虚函数析

17、构函数可以是虚函数,但构造函数不能是虚函数析构函数可以是虚函数,但构造函数不能是虚函数 动态联编只能通过动态联编只能通过动态联编只能通过动态联编只能通过指针或引用指针或引用指针或引用指针或引用来操作虚函数,如果采来操作虚函数,如果采来操作虚函数,如果采来操作虚函数,如果采用其他标识对象来操作虚函数,将采用静态联编方式用其他标识对象来操作虚函数,将采用静态联编方式用其他标识对象来操作虚函数,将采用静态联编方式用其他标识对象来操作虚函数,将采用静态联编方式调用虚函数。调用虚函数。调用虚函数。调用虚函数。Object Oriented虚析构函数虚析构函数 构造函数不能是虚函数。建立一个派生类对象时,

18、必构造函数不能是虚函数。建立一个派生类对象时,必构造函数不能是虚函数。建立一个派生类对象时,必构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的须从类层次的根开始,沿着继承路径逐个调用基类的须从类层次的根开始,沿着继承路径逐个调用基类的须从类层次的根开始,沿着继承路径逐个调用基类的构造函数构造函数构造函数构造函数 析构函数可以是虚的。虚析构函数用于指引析构函数可以是虚的。虚析构函数用于指引析构函数可以是虚的。虚析构函数用于指引析构函数可以是虚的。虚析构函数用于指引 deletedelete运算符正确析构动态对象运算符正确析构动态对象运算符正确析构动态对

19、象运算符正确析构动态对象 Object Oriented5-35-3普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;/用基类指针建立派生类的动态对象用基类指针建立派生类的动态对象B*Bp2=newB;/用派生类指针建立派生类的动态对象用派生类指针建立派生类的动态对

20、象coutdeletefirstobject:n;deleteAp;/析构由基类指针建立的派生类对象没有调用派生类构造函数析构由基类指针建立的派生类对象没有调用派生类构造函数问题?问题?coutdeletesecondobject:n;deleteBp2;/析构由派生类指针建立的派生类对象正确调用派生类构造函数析构由派生类指针建立的派生类对象正确调用派生类构造函数Object Oriented5-45-4虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况#includeclassApu

21、blic:virtualA()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;Object Oriented第二节第二节纯虚函数和抽象类纯虚函数和抽象类 纯虚函数是一个在基类中说明的虚函数,为各派生类纯虚函数是一个在基类中说明的虚函数,为各派生类纯虚函数是一个在基类中说明的虚函数,为各派生类纯虚函数是一个在基类中说明的虚

22、函数,为各派生类提供一个公共界面,在基类中没有定义,要求任何派提供一个公共界面,在基类中没有定义,要求任何派提供一个公共界面,在基类中没有定义,要求任何派提供一个公共界面,在基类中没有定义,要求任何派生类都定义自己的版本生类都定义自己的版本生类都定义自己的版本生类都定义自己的版本 纯虚函数纯虚函数纯虚函数纯虚函数 纯虚函数说明形式:纯虚函数说明形式:纯虚函数说明形式:纯虚函数说明形式:virtualvirtual类型类型类型类型 函数名(参数表)函数名(参数表)函数名(参数表)函数名(参数表)=0=0; ; 一个具有纯虚函数的基类称为抽象类。一个具有纯虚函数的基类称为抽象类。一个具有纯虚函数的

23、基类称为抽象类。一个具有纯虚函数的基类称为抽象类。 Object Orientedclassfigure/figure.hprotected:doublex,y;5-55-5public:voidset_dim(doublei,doublej=0)x=i;y=j;virtualvoidshow_area()=0;classtriangle:publicfigurepublic:voidshow_area()coutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;classsquare:publicfigurepublic:voidshow_area()

24、coutSquarewithdimensionx*yhasanareaofx*yn;classcircle:publicfigurepublic:voidshow_area()coutCirclewithradiusx;couthasanareaof3.14*x*xn;Object Oriented#include#includefigure.hvoidmain()trianglet;/派生类对象派生类对象squares;circlec;t.set_dim(10.0,5.0);t.show_area();s.set_dim(10.0,5.0);s.show_area();c.set_dim(9

25、.0);c.show_area();抽象类至少有一个纯抽象类至少有一个纯抽象类至少有一个纯抽象类至少有一个纯虚函数。虚函数。虚函数。虚函数。 如果抽象类的一个如果抽象类的一个如果抽象类的一个如果抽象类的一个派生类没有为继承的纯派生类没有为继承的纯派生类没有为继承的纯派生类没有为继承的纯虚函数定义实现版本,虚函数定义实现版本,虚函数定义实现版本,虚函数定义实现版本,则它仍然是抽象类。则它仍然是抽象类。则它仍然是抽象类。则它仍然是抽象类。Object Oriented5-65-6class point /*/ ;classshape; / 抽象类 point center ; public : p

26、oint where ( ) return center ; void move ( point p ) enter = p ; draw ( ) ; virtualvoidrotate(int)=0; / 纯虚函数 virtualvoiddraw()=0;/ 纯虚函数 ; .shape x ;/ error,抽象类不能建立对象shape *p ;/ ok,可以声明抽象类的指针shape f ( ) ;/ error, 抽象类不能作为返回类型void g ( shape ) ;/ error, 抽象类不能作为参数类型shape & h ( shape &) ;/ ok,可以声明抽象类的引用Ob

27、ject Orientedclass ab_circle : public shape int radius ; public : void rotate ( int ) ; ; ab_circle 类仍为抽象类ab_circle : draw ( ) 、ab_circle : rotate ( ) 也是纯虚函数 要使 ab_circle 成为非抽象类, 必须作以下说明: class ab_circle : public shape int radius ; public : voidrotate(int); voiddraw(); ; 并提供 ab_circle:draw() 和 ab_ci

28、rcle:rotate(int) 的定义Object Oriented5-75-7声明抽象类指针声明抽象类指针声明抽象类指针声明抽象类指针#include#includefigure.hvoidmain()figure*p;/声明抽象类指针声明抽象类指针trianglet;squares;circlec;p=&t;p-set_dim(10.0,5.0); /triangle:set_dim()p-show_area();p=&s;p-set_dim(10.0,5.0);/square:set_dim()p-show_area();p=&c;p-set_dim(9.0);/circle:set_

29、dim()p-show_area();Object Oriented5-85-8抽象类引用抽象类引用抽象类引用抽象类引用#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow

30、()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;Object Orientedvoidfun(Number&n) / 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Sho

31、w()Object Oriented应用举例应用举例应用举例应用举例求圆、圆的内切正方形及外切正方形的面积求圆、圆的内切正方形及外切正方形的面积求圆、圆的内切正方形及外切正方形的面积求圆、圆的内切正方形及外切正方形的面积及周长及周长及周长及周长 #include#include #include#include classshapeclassshapeprotected:protected:doubler;doubler;public:public:shape(doubleshape(doublex)x)r=x;r=x;virtualdoublearea()=0;virtualdoublear

32、ea()=0;virtualdoubleperimeter()=0;virtualdoubleperimeter()=0; ;Object Orientedclassclasscircle:publiccircle:publicshapeshapepublic:public:circle(doublecircle(double x):shape(xx):shape(x) )doublearea()doublearea()return3.14*r*r;return3.14*r*r;doubleperimeter()doubleperimeter()return2*3.14*r;return2*3

33、.14*r; ;classclassin_square:publicin_square:publicshapeshapepublic:public:in_square(doublein_square(double x):shape(xx):shape(x) )doublearea()doublearea()return2*r*r;return2*r*r;doubleperimeter()doubleperimeter()return4*sqrt(2)*r;return4*sqrt(2)*r; ;Object Orientedclassclassex_square:publicex_square

34、:publicshapeshapepublic:public:ex_square(doubleex_square(double x):shape(xx):shape(x) )doublearea()doublearea()return4*r*r;return4*r*r;doubleperimeter()doubleperimeter()return8*r;return8*r; ;voidmain()voidmain()shape*p;shape*p;circleob1(5.0);circleob1(5.0); in_squarein_squareob2(5.0);ob2(5.0); ex_sq

35、uareex_squareob3(5);ob3(5);p=&ob1;p=&ob1; coutcoutCircle:area=area();Circle:area=area(); coutcoutperimeter=perimeter()perimeter=perimeter()endlendl; ;p=&ob2;p=&ob2; coutcoutInternal:area=area();Internal:area=area(); coutcoutperimeter=perimeter()perimeter=perimeter()endlendl; ;p=&ob3;p=&ob3; coutcout

36、External:area=area();External:area=area(); coutcoutperimeter=perimeter()perimeter=perimeter()endlendl; ; ;Object Oriented第三节第三节运算符重载运算符重载运算符重载使得用户自定义的数据以一种更简洁的运算符重载使得用户自定义的数据以一种更简洁的运算符重载使得用户自定义的数据以一种更简洁的运算符重载使得用户自定义的数据以一种更简洁的方式工作,就是赋予已有的运算符多重含义。方式工作,就是赋予已有的运算符多重含义。方式工作,就是赋予已有的运算符多重含义。方式工作,就是赋予已有的运算符

37、多重含义。例如例如intx,y ;y=x+y;matrixm1,m2;/ 矩阵类对象矩阵类对象m2=Madd(m1,m2);/ 调用函数计算两个矩阵的和调用函数计算两个矩阵的和complexc1,c2;/ 复数类对象复数类对象c1=Cadd(c1,c2);/ 调用函数计算两个复数的和调用函数计算两个复数的和能表示为能表示为c1=c1+c2;?能表示为能表示为m1=m1+m2;?Object Oriented类以外的运算符重载类以外的运算符重载类以外的运算符重载类以外的运算符重载#include#include classcomplexclasscomplexpublic:public:doub

38、lereal;doublereal;doubledoubleimagimag; ; complex(doublecomplex(doubler=0,doublei=0)r=0,doublei=0)real=real=r;imagr;imag=i;=i; ;complexcomplexoperator+(complexoperator+(complexco1,complexco2)/co1,complexco2)/运算符运算符运算符运算符“ “+”+”的重载函数的重载函数的重载函数的重载函数complextemp;complextemp; temp.realtemp.real=co1.real+

39、co2.real;=co1.real+co2.real; temp.imagtemp.imag=co1.imag+co2.imag;=co1.imag+co2.imag;returntemp;returntemp; voidmain()voidmain()complexcom1(1.1,2.2),com2(3.3,4.4),total1,total2;complexcom1(1.1,2.2),com2(3.3,4.4),total1,total2; total1=operator+(com1,com2);/total1=operator+(com1,com2);/运算符重载的使用方法运算符重载

40、的使用方法运算符重载的使用方法运算符重载的使用方法1 1 coutcoutreal1=total1.real;real1=total1.real; coutcoutimag1=total1.imagimag1=total1.imagendlendl; ; total2=com1+com2;/total2=com1+com2;/运算符重载的使用方法运算符重载的使用方法运算符重载的使用方法运算符重载的使用方法2 2 coutcoutreal2=total2.real;real2=total2.real; coutcoutimag2=total2.imagimag2=total2.imagendle

41、ndl; ; Object Oriented一、运算符重载的实质一、运算符重载的实质一、运算符重载的实质一、运算符重载的实质 uu运算符重载是对已有的运算符赋予多重含义运算符重载是对已有的运算符赋予多重含义运算符重载是对已有的运算符赋予多重含义运算符重载是对已有的运算符赋予多重含义 uu必要性必要性必要性必要性 C+C+C+C+中预定义的运算符其运算对象只能是基本数据类型,中预定义的运算符其运算对象只能是基本数据类型,中预定义的运算符其运算对象只能是基本数据类型,中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)而不适用于用户自定义类型(如类)而不适用于用户自定义类

42、型(如类)而不适用于用户自定义类型(如类) uu实现机制实现机制实现机制实现机制 uu将指定的运算表达式转化为对运算符函数的调用,运算将指定的运算表达式转化为对运算符函数的调用,运算将指定的运算表达式转化为对运算符函数的调用,运算将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。对象转化为运算符函数的实参。对象转化为运算符函数的实参。对象转化为运算符函数的实参。 相当于相当于相当于相当于a+ba+b=+(+(a,ba,b) )uu编译系统对重载运算符的选择,遵循函数重载的选择原编译系统对重载运算符的选择,遵循函数重载的选择原编译系统对重载运算符的选择,遵循函数重载的选

43、择原编译系统对重载运算符的选择,遵循函数重载的选择原则。则。则。则。 相当于选相当于选相当于选相当于选+ +(1 1,2 2)还是)还是)还是)还是+ +(1 1,1 1),(),(),(),(2 2,2 2)?)?)?)?Object Oriented二、重载运算符的限制二、重载运算符的限制二、重载运算符的限制二、重载运算符的限制1 1 1 1、不能重载的算符、不能重载的算符、不能重载的算符、不能重载的算符 . . . .:* * * *?:?:?:?:# # # # sizeofsizeofsizeofsizeof2 2 2 2、重载运算符可以对运算符作出新的解释,但原有基本语义、重载运算

44、符可以对运算符作出新的解释,但原有基本语义、重载运算符可以对运算符作出新的解释,但原有基本语义、重载运算符可以对运算符作出新的解释,但原有基本语义不变:不变:不变:不变:不改变运算符的优先级和结合性不改变运算符的优先级和结合性不改变运算符的优先级和结合性不改变运算符的优先级和结合性。(否则难以记忆)(否则难以记忆)(否则难以记忆)(否则难以记忆)不改变运算符所需要的操作数,即单目运算符只能重载不改变运算符所需要的操作数,即单目运算符只能重载不改变运算符所需要的操作数,即单目运算符只能重载不改变运算符所需要的操作数,即单目运算符只能重载为单目运算符,不能将单目运算符重载为双目运算符。为单目运算符

45、,不能将单目运算符重载为双目运算符。为单目运算符,不能将单目运算符重载为双目运算符。为单目运算符,不能将单目运算符重载为双目运算符。不能创建新的运算符,只有系统预定义的运算符才能被不能创建新的运算符,只有系统预定义的运算符才能被不能创建新的运算符,只有系统预定义的运算符才能被不能创建新的运算符,只有系统预定义的运算符才能被重载。重载。重载。重载。经重载的运算符,其操作数中至少应该有一个是自定义经重载的运算符,其操作数中至少应该有一个是自定义经重载的运算符,其操作数中至少应该有一个是自定义经重载的运算符,其操作数中至少应该有一个是自定义类型。类型。类型。类型。(否则系统已经实现了)(否则系统已经

46、实现了)(否则系统已经实现了)(否则系统已经实现了) 3 3 3 3、运算符通常是对类中的私有成员进行操作,故重载运算符、运算符通常是对类中的私有成员进行操作,故重载运算符、运算符通常是对类中的私有成员进行操作,故重载运算符、运算符通常是对类中的私有成员进行操作,故重载运算符应能访问类中的私有成员,所以重载运算符一般采用应能访问类中的私有成员,所以重载运算符一般采用应能访问类中的私有成员,所以重载运算符一般采用应能访问类中的私有成员,所以重载运算符一般采用成员成员成员成员函数函数函数函数或或或或友员函数友员函数友员函数友员函数的形式的形式的形式的形式Object Oriented三、重载为类成

47、员函数三、重载为类成员函数三、重载为类成员函数三、重载为类成员函数语法形式为:语法形式为:语法形式为:语法形式为:类型类型类型类型 类名类名类名类名 : operator op ( : operator op ( : operator op ( : operator op ( 参数表参数表参数表参数表 ) ) ) ) / / / / 相对于该类定义的操作相对于该类定义的操作相对于该类定义的操作相对于该类定义的操作 其中,当为双目运算符时,参数表中为一个参数,单目运其中,当为双目运算符时,参数表中为一个参数,单目运其中,当为双目运算符时,参数表中为一个参数,单目运其中,当为双目运算符时,参数表中

48、为一个参数,单目运算符时,参数表为空算符时,参数表为空算符时,参数表为空算符时,参数表为空通过通过通过通过thisthisthisthis指针传递。指针传递。指针传递。指针传递。 Object Oriented( ( ( (一)双目运算符的重载一)双目运算符的重载一)双目运算符的重载一)双目运算符的重载例例例例【5.3.25.3.2】重载二个复数对象的加、减、乘、除重载二个复数对象的加、减、乘、除重载二个复数对象的加、减、乘、除重载二个复数对象的加、减、乘、除运算符运算符运算符运算符熟悉双目运算符的重载。熟悉双目运算符的重载。熟悉双目运算符的重载。熟悉双目运算符的重载。1 1、分析:设两个复数

49、、分析:设两个复数、分析:设两个复数、分析:设两个复数a+bia+bi和和和和c+dic+di,则有:,则有:,则有:,则有:加法:加法:加法:加法:( (a+bi)+(c+dia+bi)+(c+di)=()=(a+c)+(b+d)ia+c)+(b+d)i; ;减法:减法:减法:减法:( (a+bi)-(c+dia+bi)-(c+di)=(a-)=(a-c)+(b-d)ic)+(b-d)i; ;乘法:乘法:乘法:乘法:( (a+bia+bi)*()*(c+dic+di)=(ac-)=(ac-bd)+(ad+bc)ibd)+(ad+bc)i除法:除法:除法:除法:( (a+bi)/(c+dia+

50、bi)/(c+di)=()=(a+bia+bi)*(c-di)/(c)*(c-di)/(c2 2+d+d2 2) )=(=(ac+bdac+bd)/(c)/(c2 2+d+d2 2)+(bc-ad)i/(c)+(bc-ad)i/(c2 2+d+d2 2) )2 2、程序:、程序:、程序:、程序:Object Oriented#include#include classcomplexclasscomplexprivate:private:doublereal;doublereal;doubledoubleimagimag; ;public:public:complex(doublecomplex

51、(doubler=0,doublei=0)r=0,doublei=0)real=real=r;imagr;imag=i;=i;complexcomplexoperator+(complexoperator+(complexc);c);complexoperator-(complexc);complexoperator-(complexc);complexoperator*(complexc);complexoperator*(complexc);complexoperator/(complexc);complexoperator/(complexc);voidprint();voidprint

52、(); ;2个操作数Object Orientedcomplexcomplexcomplexcomplex:operator+(complexoperator+(complexcc)/)/重载重载重载重载“ “+”+”complextemp;complextemp; temp.realtemp.real= =real+c.realreal+c.real; ; temp.imagtemp.imag= =imag+c.imagimag+c.imag; ;returntemp;returntemp; complexcomplexcomplexcomplex:operator-(complexc)/:

53、operator-(complexc)/重载重载重载重载“ “- -” ”complextemp;complextemp;temp.realtemp.real=real-=real-c.realc.real; ;temp.imagtemp.imag= =imag-c.imagimag-c.imag; ;returntemp;returntemp; Object Orientedcomplexcomplexcomplexcomplex:operator*(complexc)/:operator*(complexc)/重载重载重载重载“*”“*”complextemp;complextemp; t

54、emp.realtemp.real=real*=real*c.real-imagc.real-imag* *c.imagc.imag; ; temp.imagtemp.imag=real*=real*c.imag+imagc.imag+imag* *c.realc.real; ;returntemp;returntemp; complexcomplexcomplexcomplex:operator/(complexc)/:operator/(complexc)/重载重载重载重载“ “/”/”complextemp;complextemp;doublet;doublet;t=t=c.realc.

55、real* *c.real+c.imagc.real+c.imag* *c.imagc.imag; ; temp.realtemp.real=(real*=(real*c.real+imagc.real+imag* *c.imag)/tc.imag)/t; ; temp.imagtemp.imag=(=(c.realc.real* *imagimag-real*-real*c.imag)/tc.imag)/t; ;returntemp;returntemp; Object Orientedvoidvoidcomplex:printcomplex:print() () coutcoutreal;

56、0)0)coutcout+;+;if(if(imagimag!=0)!=0)coutcoutimagimagiiendlendl; ; voidmain()voidmain()complexA1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;complexA1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;A3=A1+A2;A4=A1-A2;A3=A1+A2;A4=A1-A2;A5=A1*A2;A6=A1/A2;A5=A1*A2;A6=A1/A2;A1.print();A2.print();A1.print();A2.print();A3.print()

57、;A4.print();A3.print();A4.print();A5.print();A6.print();A5.print();A6.print(); Object Oriented(二)单目运算符重载(二)单目运算符重载(二)单目运算符重载(二)单目运算符重载(单目运算符重载时没有参数。(单目运算符重载时没有参数。(单目运算符重载时没有参数。(单目运算符重载时没有参数。) )前置和后置,函数名都是前置和后置,函数名都是前置和后置,函数名都是前置和后置,函数名都是operator+operator+,所以人为给后置多加一个哑参数,所以人为给后置多加一个哑参数,所以人为给后置多加一个哑参数

58、,所以人为给后置多加一个哑参数, ,只有类型名。只有类型名。只有类型名。只有类型名。例例【5.3.3】运算符前置运算符前置+和后置和后置+重载为时重载为时钟类的成员函数。钟类的成员函数。u前置单目运算符,重载函数没有形参,对于后置前置单目运算符,重载函数没有形参,对于后置前置单目运算符,重载函数没有形参,对于后置前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数需要有一个整型形参。单目运算符,重载函数需要有一个整型形参。单目运算符,重载函数需要有一个整型形参。单目运算符,重载函数需要有一个整型形参。 u操作数是时钟类的对象。操作数是时钟类的对象。操作数是时钟类的对象。操作数是时钟类

59、的对象。 u实现时间增加实现时间增加实现时间增加实现时间增加1 1秒钟。秒钟。秒钟。秒钟。Object Oriented#includeclassClock/时钟类声明时钟类声明public:/外部接口外部接口Clock(intNewH=0,intNewM=0,intNewS=0)Hour=NewH;Minute=NewM;Second=NewS;voidShowTime()coutHour:Minute:Second=60)/考虑进位考虑进位Second=Second-60;Minute+;if(Minute=60)Minute=Minute-60;Hour+;Hour=Hour%24;co

60、ut=60)Second=Second-60;Minute+;if(Minute=60)Minute=Minute-60;Hour+;Hour=Hour%24;coutClock+:;Object Orientedvoidmain()ClockmyClock(23,59,59);coutFirsttimeoutput:;myClock.ShowTime();myClock+;myClock.ShowTime();+myClock;myClock.ShowTime();Object Oriented四、重载为友元函数四、重载为友元函数四、重载为友元函数四、重载为友元函数例例例例【5.3.45.3

61、.45.3.45.3.4】将将将将+ + + +、- - - -(双目)重载为复数类的友元函数。(双目)重载为复数类的友元函数。(双目)重载为复数类的友元函数。(双目)重载为复数类的友元函数。 两个操作数都是复数类的对象。两个操作数都是复数类的对象。两个操作数都是复数类的对象。两个操作数都是复数类的对象。#include#include classcomplexclasscomplexprivate:private:doublereal;doublereal;doubledoubleimagimag; ;public:public:complex(doublecomplex(doubler=0

62、,doublei=0)r=0,doublei=0)real=real=r;imagr;imag=i;=i;voidprint();voidprint();friendcomplexfriendcomplexoperator+(complexoperator+(complex a,complexa,complexb);b);friendcomplexoperator-(complexfriendcomplexoperator-(complexa,complexa,complexb);b);friendcomplexoperator*(complexfriendcomplexoperator*(c

63、omplexa,complexa,complexb);b);friendcomplexoperator/(complexfriendcomplexoperator/(complexa,complexa,complexb);b); ;Object Orientedcomplexcomplexoperator+(complexoperator+(complex a,complexa,complexb)b)complextemp;complextemp; temp.realtemp.real= =a.real+b.reala.real+b.real; ; temp.imagtemp.imag= =a

64、.imag+b.imaga.imag+b.imag; ;returntemp;returntemp; complexoperator-(complexcomplexoperator-(complexa,complexa,complexb)b)complextemp;complextemp; temp.realtemp.real= =a.real-b.reala.real-b.real; ; temp.imagtemp.imag= =a.imag-b.imaga.imag-b.imag; ;returntemp;returntemp; Object Orientedcomplexoperator

65、*(complexcomplexoperator*(complexa,complexa,complexb)b)complextemp;complextemp; temp.realtemp.real= =a.reala.real* *b.real-a.imagb.real-a.imag* *b.imagb.imag; ; temp.imagtemp.imag= =a.reala.real* *b.imag+a.imagb.imag+a.imag* *b.realb.real; ;returntemp;returntemp; complexoperator/(complexcomplexopera

66、tor/(complexa,complexa,complexb)b)complextemp;complextemp;doublet;doublet;t=t=b.realb.real* *b.real+b.imagb.real+b.imag* *b.imagb.imag; ; temp.realtemp.real=(=(a.reala.real* *b.real+a.imagb.real+a.imag* *b.imag)/tb.imag)/t; ; temp.imagtemp.imag=(=(b.realb.real* *a.imag-a.reala.imag-a.real* *b.imag)/

67、tb.imag)/t; ;returntemp;returntemp; Object Orientedvoidvoidcomplex:printcomplex:print() () coutcoutreal;0)0)coutcout+;+;if(if(imagimag!=0)!=0)coutcoutimagimagii-不能用友元函数重载,(只能用成不能用友元函数重载,(只能用成不能用友元函数重载,(只能用成不能用友元函数重载,(只能用成员函数重载)员函数重载)员函数重载)员函数重载)Object Orientedclassclassnclassnclass private:private:i

68、ntinta;a;intintb;b;public:public: nclassnclass operator+(intoperator+(intx);x); ;nclassnclass nclassnclass:operator+(intoperator+(intx)x) nclassnclasstemp;temp; temp.atemp.a= =a+xa+x; ; temp.btemp.b= =b+xb+x; ;returntemp;returntemp; voidmain()voidmain() nclassnclassob1,ob2;ob1,ob2;ob2=ob1+100;ob2=ob

69、1+100;ob2=100+ob1;ob2=100+ob1; 程序中:程序中:程序中:程序中:ob2=ob1+100;ob2=ob1+100;正确正确正确正确ob2=100+ob1;ob2=100+ob1;不正确,为什么?不正确,为什么?不正确,为什么?不正确,为什么?Object Oriented例例例例【5.3.55.3.55.3.55.3.5】常数与复数相加。常数与复数相加。常数与复数相加。常数与复数相加。#include#include classcomplexclasscomplexprivate:private:doublereal;doublereal;doubledoublei

70、magimag; ;public:public: complex(doublecomplex(doubler=0,doublei=0)r=0,doublei=0)real=real=r;imagr;imag=i;=i;voidshow()voidshow()coutcoutreal=realreal=realimagimag=imagimagendlendl; ;friendcomplexfriendcomplexoperator+(complexoperator+(complex co,doubleco,doublex);x);friendcomplexfriendcomplexoperat

71、or+(doubleoperator+(double x,complexx,complexco);co); ;Object Orientedcomplexcomplexoperator+(complexoperator+(complex co,doubleco,doublex)x)complextemp;complextemp; temp.realtemp.real= =co.real+xco.real+x; ; temp.imagtemp.imag= =co.imagco.imag; ;returntemp;returntemp; complexcomplexoperator+(double

72、operator+(double x,complexx,complexco)co)complextemp;complextemp; temp.realtemp.real= =x+co.realx+co.real; ; temp.imagtemp.imag= =co.imagco.imag; ;returntemp;returntemp; voidmain()voidmain()complexcom1(1.1,2.2),com2,com3;complexcom1(1.1,2.2),com2,com3;com2=com1+10.0;com2=com1+10.0;com2.show();com2.s

73、how();com3=20.0+com1;com3=20.0+com1;com3.show();com3.show(); Object Oriented五、赋值运算符五、赋值运算符五、赋值运算符五、赋值运算符“=”=”=”=”的重载的重载的重载的重载同拷贝构造函数一样,通常同拷贝构造函数一样,通常同拷贝构造函数一样,通常同拷贝构造函数一样,通常“=”=”=”=”不用重载,同一类的对象不用重载,同一类的对象不用重载,同一类的对象不用重载,同一类的对象可直接赋值。如:可直接赋值。如:可直接赋值。如:可直接赋值。如:ob1=ob2;ob1=ob2;ob1=ob2;ob1=ob2;当在类中用当在类中用

74、当在类中用当在类中用newnew分配内存空间,在析构函数中用分配内存空间,在析构函数中用分配内存空间,在析构函数中用分配内存空间,在析构函数中用deletedelete中中中中释放内存空间时,应重载释放内存空间时,应重载释放内存空间时,应重载释放内存空间时,应重载“ “=”=”运算符。运算符。运算符。运算符。例例例例【5.3.65.3.65.3.65.3.6】调试下列程序,分析出错的原因调试下列程序,分析出错的原因调试下列程序,分析出错的原因调试下列程序,分析出错的原因#include#include #include#includeclassstringclassstringchar*cha

75、r*ptrptr; ;public:public:string(char*s)string(char*s)ptrptr=newcharstrlen(s)+1;=newcharstrlen(s)+1; strcpy(ptr,sstrcpy(ptr,s););string()deletestring()deleteptrptr; ;voidprint()voidprint()coutcoutptrptrendlendl; ; ;voidmain()voidmain()stringp1(chen);stringp1(chen);stringp2();stringp2(); p2=p1;p2=p1;

76、coutcoutp2:;p2:; p2.print();p2.print(); coutcoutp1:;p1:;p1.print();p1.print(); Object Orientedvoidmain()voidmain()stringp1(chen);stringp1(chen);stringp2();stringp2(); p2=p1;p2=p1; coutcoutp2:;p2:; p2.print();p2.print(); coutcoutp1:;p1:;p1.print();p1.print(); Object Oriented出错原因分析:出错原因分析:出错原因分析:出错原因分

77、析:ptrptrptrptr动态空间动态空间动态空间动态空间1 1 1 1P1P1P1P1ptrptrptrptr动态空间动态空间动态空间动态空间2 2 2 2P2P2P2P2(a) (a) (a) (a) 执行执行执行执行p2=p1p2=p1p2=p1p2=p1前前前前ptrptrptrptrP1P1P1P1ptrptrptrptrP2P2P2P2(b) (b) (b) (b) 执行执行执行执行p2=p1p2=p1p2=p1p2=p1后后后后ptrptrptrptrP1P1P1P1(c) p2(c) p2(c) p2(c) p2释放后释放后释放后释放后?Object Oriented解决办法

78、:重载解决办法:重载解决办法:重载解决办法:重载“ “=”=”运算符运算符运算符运算符例例例例【5.3.75.3.75.3.75.3.7】将上例程序改为:将上例程序改为:将上例程序改为:将上例程序改为:#include#include #include#includeclassstringclassstringchar*char*ptrptr; ;public:public:string(char*s)string(char*s)ptrptr=newcharstrlen(s)+1;=newcharstrlen(s)+1; strcpy(ptr,sstrcpy(ptr,s); );string(

79、)string()deletedeleteptrptr; ;voidprint()voidprint()coutcoutptrptrendlendl; ; string&operator=(conststring&s);string&operator=(conststring&s); ;Object Orientedstring&string&string:operatorstring:operator=(const=(conststring&sstring&s)/)/重载重载重载重载“ “=”=”运算符运算符运算符运算符 if(thisif(this=&s)return*this;/=&s)

80、return*this;/当用当用当用当用“ “ob1=ob1=ob1ob1;”;”时时时时 deletedeleteptrptr;/;/首先释放被赋值对象的空间首先释放被赋值对象的空间首先释放被赋值对象的空间首先释放被赋值对象的空间 ptrptr=newcharstrlen(s.ptr)+1;/=newcharstrlen(s.ptr)+1;/重新为被赋值对象分配空间重新为被赋值对象分配空间重新为被赋值对象分配空间重新为被赋值对象分配空间 strcpy(ptr,s.ptrstrcpy(ptr,s.ptr); );return*this;return*this; voidmain()voidm

81、ain() stringp1(chen);stringp1(chen);stringp2();stringp2(); p2=p1;p2=p1; p2.print();p2.print(); p1.print();p1.print(); 说明:说明:说明:说明:类的赋值运算符类的赋值运算符类的赋值运算符类的赋值运算符“=”=”=”=”只能重载为成只能重载为成只能重载为成只能重载为成员函数,重载后不能员函数,重载后不能员函数,重载后不能员函数,重载后不能被继承。被继承。被继承。被继承。 Object Oriented注意:对象初始化时的赋值和已创建对象之间的赋值注意:对象初始化时的赋值和已创建对象

82、之间的赋值注意:对象初始化时的赋值和已创建对象之间的赋值注意:对象初始化时的赋值和已创建对象之间的赋值虽然都涉及对象的复制,但它们是两个不同的操作。虽然都涉及对象的复制,但它们是两个不同的操作。虽然都涉及对象的复制,但它们是两个不同的操作。虽然都涉及对象的复制,但它们是两个不同的操作。对象初始化首先是为新对象分配存储空间,然后执行对象初始化首先是为新对象分配存储空间,然后执行对象初始化首先是为新对象分配存储空间,然后执行对象初始化首先是为新对象分配存储空间,然后执行对象复制。对象复制。对象复制。对象复制。如:如:如:如:Pointp1,p2(3.14,4.06);Pointp1,p2(3.14

83、,4.06);Pointp3=p2;/Pointp3=p2;/调用拷贝构造初始化函数调用拷贝构造初始化函数调用拷贝构造初始化函数调用拷贝构造初始化函数p1=p2;/p1=p2;/调用赋值运算符重载调用赋值运算符重载调用赋值运算符重载调用赋值运算符重载Object Oriented本章小结本章小结 多态:多态:多态:多态: 同样的消息被不同类型的对象接收时导致完全不同的行同样的消息被不同类型的对象接收时导致完全不同的行同样的消息被不同类型的对象接收时导致完全不同的行同样的消息被不同类型的对象接收时导致完全不同的行为,是对类的特定成员函数的再抽象。为,是对类的特定成员函数的再抽象。为,是对类的特定

84、成员函数的再抽象。为,是对类的特定成员函数的再抽象。 运算符重载运算符重载运算符重载运算符重载 对已有的运算符赋予多重含义,使用已有运算符对用户对已有的运算符赋予多重含义,使用已有运算符对用户对已有的运算符赋予多重含义,使用已有运算符对用户对已有的运算符赋予多重含义,使用已有运算符对用户自定义类型自定义类型自定义类型自定义类型( (比如类比如类比如类比如类) )进行运算操作。进行运算操作。进行运算操作。进行运算操作。 联编联编联编联编 程序自身彼此关联的过程称为联编,联编确定程序中的程序自身彼此关联的过程称为联编,联编确定程序中的程序自身彼此关联的过程称为联编,联编确定程序中的程序自身彼此关联

85、的过程称为联编,联编确定程序中的操作调用与执行该操作的代码间的关系。操作调用与执行该操作的代码间的关系。操作调用与执行该操作的代码间的关系。操作调用与执行该操作的代码间的关系。 静态联编工作出现在编译阶段。静态联编工作出现在编译阶段。静态联编工作出现在编译阶段。静态联编工作出现在编译阶段。 动态联编工作在程序运行时执行。虚函数是动态联编的动态联编工作在程序运行时执行。虚函数是动态联编的动态联编工作在程序运行时执行。虚函数是动态联编的动态联编工作在程序运行时执行。虚函数是动态联编的基础。基础。基础。基础。 Object Oriented 纯虚函数纯虚函数纯虚函数纯虚函数 在基类中说明的虚函数,它

86、在该基类中可以不给出函数在基类中说明的虚函数,它在该基类中可以不给出函数在基类中说明的虚函数,它在该基类中可以不给出函数在基类中说明的虚函数,它在该基类中可以不给出函数体,要求各派生类根据实际需要编写自己的函数体。体,要求各派生类根据实际需要编写自己的函数体。体,要求各派生类根据实际需要编写自己的函数体。体,要求各派生类根据实际需要编写自己的函数体。 抽象类抽象类抽象类抽象类 带有纯虚函数的类是抽象类。带有纯虚函数的类是抽象类。带有纯虚函数的类是抽象类。带有纯虚函数的类是抽象类。 抽象类的主要作用是通过它为一个类族建立一个公共的抽象类的主要作用是通过它为一个类族建立一个公共的抽象类的主要作用是

87、通过它为一个类族建立一个公共的抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。接口,使它们能够更有效地发挥多态特性。接口,使它们能够更有效地发挥多态特性。接口,使它们能够更有效地发挥多态特性。Object Oriented练习1 1、分别使用成员函数和友员函数编程序重载运算符、分别使用成员函数和友员函数编程序重载运算符、分别使用成员函数和友员函数编程序重载运算符、分别使用成员函数和友员函数编程序重载运算符“ “+”+”,使该运算符能实现两个字符串的连接。使该运算符能实现两个字符串的连接。使该运算符能实现两个字符串的连接。使该运算符能实现两个字符串的连接。

88、Object Oriented#includeiostream.h#includeclassstringpublic:string()*str=0;string(char*pstr)strcpy(str,pstr);char*gets()returnstr;stringoperator+(stringobj);private:charstr100;stringstring:operator+(stringobj)strcat(str,obj.str);returnstr;/或或return*thisvoidmain()stringobj1(Visual),obj2(C+),obj3;obj3=

89、obj1+obj2;coutobj3.gets()endl;Object Oriented#include#includeclassstringpublic:string()*str=0;string(char*pstr)strcpy(str,pstr);char*gets()returnstr;friendstringoperator+(stringobj1,stringobj2);private:charstr100;stringoperator+(stringobj1,stringobj2)stringtempobj;strcat(tempobj.str,obj1.str);strcat

90、(tempobj.str,obj2.str);returntempobj;voidmain()stringobj1(Visual),obj2(C+),obj3;obj3=obj1+obj2;coutobj3.gets()next=h;h=t;voidtest3()/ 测试函数测试函数Employee*empHead=NULL,*ptr;ptr=newManager(10135,ChengShaoHua,1200);/ 建立第一个结点建立第一个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newHourlyWorker(30712,ZhaoXiaoMing,5,8*

91、20);/ 建立第二建立第二个结点个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newPieceWorker(20382,XiuLiWei,0.5,2850);/ 建立第三个结点建立第三个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=empHead;while(ptr)ptr-print();ptr=ptr-next;/ 遍历链表,输出全部信遍历链表,输出全部信息息ptr=empHead;while(ptr)/ 遍历链表,输出姓名和工资遍历链表,输出姓名和工资coutgetName()earnings()next;Object Or

92、ientedfor1for1:#include#includeclassPointpublic:Point(doublexi,doubleyi)X=xi;Y=yi;doubleGetX()returnX;doubleGetY()returnY;frienddoubleDistance(Point&a,Point&b);private:doubleX,Y;doubleDistance(Point&a,Point&b)doubledx=a.X-b.X;doubledy=a.Y-b.Y;returnsqrt(dx*dx+dy*dy);voidmain()Pointp1(3.0,5.0),p2(4.0

93、,6.0);doubled=Distance(p1,p2);coutThisdistanceisdendl;Object Orientedfor2for2:类和对象:类和对象:类和对象:类和对象定义一个正方形类,该类包括:定义一个正方形类,该类包括:(1 1)受保护类数据成员,表示正方形类的边长,取)受保护类数据成员,表示正方形类的边长,取值范围在值范围在1-301-30 (2 2)四个成员函数,分别为:)四个成员函数,分别为:u 带参构造函数,初始化正方形边长;带参构造函数,初始化正方形边长;u 取边长函数取边长函数GetLenGetLen( )( );u 设置边长函数设置边长函数 SetL

94、enSetLen( )( ),重新设置边长,并检查重新设置边长,并检查是否在规定范围内;是否在规定范围内;u 画正方形函数画正方形函数 DrawSquareDrawSquare ( ) ( ),用边长做为行数和用边长做为行数和每行输出个数,输出每行输出个数,输出“*”“*”; (3) (3) 主函数:创建一个边长为主函数:创建一个边长为5 5的正方形;输出的正方形;输出正方形,由键盘修改边长为正方形,由键盘修改边长为8 8;重新输出正方形。;重新输出正方形。Object Orientedfor3for3:继承和派生:继承和派生:继承和派生:继承和派生设计两个类,一个类描述点,另一个类描述圆。圆

95、设计两个类,一个类描述点,另一个类描述圆。圆由圆心和半径构成,圆类由点类派生而来,圆心的由圆心和半径构成,圆类由点类派生而来,圆心的特性描述由点类继承下来。要求圆类提供特性描述由点类继承下来。要求圆类提供: (1 1)求圆面积的成员函数)求圆面积的成员函数 (2 2) 取圆心坐标的两个函数取圆心坐标的两个函数 Get_XGet_X( )( )和和Get_YGet_Y( ( ) ) (3) (3) 支持初始化的带参构造函数支持初始化的带参构造函数 (4) (4) 主函数,键盘输入圆心坐标主函数,键盘输入圆心坐标 x,yx,y, , 以及以及半径半径 r, r, 输出圆面积。输出圆面积。Objec

96、t Orientedfor4for4:继承和派生:继承和派生:继承和派生:继承和派生一个图形是由一个圆和一个矩形构成,要求求解图一个图形是由一个圆和一个矩形构成,要求求解图形的面积。设计形的面积。设计3 3个类,其中两个是基类,一个基个类,其中两个是基类,一个基类描述圆,另一个基类描述矩形,第三个派生类是类描述圆,另一个基类描述矩形,第三个派生类是由一个圆和一个矩形构成的图形类。圆类包含数据由一个圆和一个矩形构成的图形类。圆类包含数据成员半径和求圆面积的成员函数,矩形类包含数据成员半径和求圆面积的成员函数,矩形类包含数据成员长和宽、求矩形面积的成员函数。派生的图形成员长和宽、求矩形面积的成员函

97、数。派生的图形类提供输出面积的函数及实现初始化的带参构造函类提供输出面积的函数及实现初始化的带参构造函数。数。 (圆半径(圆半径 r=10, r=10, 矩形矩形 长长=20, =20, 宽宽=50=50,输出面,输出面积)积)Object Orientedfor5for5:虚函数:虚函数:虚函数:虚函数编一个程序计算正方体,球体和圆柱体的表面积和编一个程序计算正方体,球体和圆柱体的表面积和体积。体积。要求:抽象出一个公共基类要求:抽象出一个公共基类containercontainer为抽象类,为抽象类,在其中定义求表面积和体积的纯虚函数。抽象类中在其中定义求表面积和体积的纯虚函数。抽象类中定

98、义一个公共的数据成员定义一个公共的数据成员radius,radius,此数值可以作为此数值可以作为球体的半径、正方体的边长、圆柱体底面圆半径。球体的半径、正方体的边长、圆柱体底面圆半径。由该抽象类派生出的三个类,都有求表面积和体积由该抽象类派生出的三个类,都有求表面积和体积的实际定义。键盘输入的实际定义。键盘输入radiusradius的值后,可以输出这的值后,可以输出这3 3种立方体的面积。种立方体的面积。Object Orientedfor6for6:函数重载:函数重载:函数重载:函数重载设计一个用来表示直角坐标系上点的位置的设计一个用来表示直角坐标系上点的位置的LocationLocat

99、ion类,然后在主程序中创建两个对象类,然后在主程序中创建两个对象A A和和B,B,要求要求A A在第三象限,在第三象限,B B在第二象限,计算给定两点在第二象限,计算给定两点之间的距离并按如下格式输出结果:之间的距离并按如下格式输出结果: A(x1,y1),B(x2,y2)A(x1,y1),B(x2,y2) Distance=d Distance=d其中其中x1,y1,x2,y2x1,y1,x2,y2为指定值,为指定值,d d为计算结果。为计算结果。Object Orientedfor7for7类的应用类的应用类的应用类的应用一圆型游泳池如图所示,现在需在其周围建一圆型一圆型游泳池如图所示,

100、现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为过道,并在其四周围上栅栏。栅栏价格为3535元元/ /米,米,过道造价为过道造价为2020元元/ /平方米。过道宽度为平方米。过道宽度为3 3米,游泳池米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏半径由键盘输入。要求编程计算并输出过道和栅栏的造价。的造价。游泳池过道Object Oriented复习结构类型用结构类型用structstruct定义,是用户自定义数据类型,由不同定义,是用户自定义数据类型,由不同类型的数据成员组成。结构变量在内存占有一片连续的存类型的数据成员组成。结构变量在内存占有一片连续的存储区间。结构变量成员

101、用圆点运算符和箭头运算符访问。储区间。结构变量成员用圆点运算符和箭头运算符访问。类类型是结构类型的拓展,通常用关键字类类型是结构类型的拓展,通常用关键字classclass定义。类是定义。类是数据成员和成员函数的封装。类的实例称为对象。数据成员和成员函数的封装。类的实例称为对象。数据成员是类的属性,可以为各种合法的数据成员是类的属性,可以为各种合法的C+C+类型,包括类类型,包括类类型。成员函数用于操作类的数据或在对象之间发送消息。类型。成员函数用于操作类的数据或在对象之间发送消息。类成员由类成员由private, protected, publicprivate, protected, pu

102、blic决定访问特性。决定访问特性。publicpublic成员集称为类的接口。不能在类的外部访问成员集称为类的接口。不能在类的外部访问privateprivate成员。成员。构造函数是特殊的成员函数,在创建和初始化对象时自动构造函数是特殊的成员函数,在创建和初始化对象时自动调用。析构函数则在对象作用域结束时自动调用。调用。析构函数则在对象作用域结束时自动调用。Object Oriented静态成员是局部于类的成员,它提供一种同类对象的共享静态成员是局部于类的成员,它提供一种同类对象的共享机制。静态数据成员在编译时建立并初始化存储空间。静机制。静态数据成员在编译时建立并初始化存储空间。静态数据

103、成员和静态成员函数依赖于类而使用,与是否建立态数据成员和静态成员函数依赖于类而使用,与是否建立对象无关。对象无关。友员是类对象操作的一种辅助手段。一个类的友员可以访友员是类对象操作的一种辅助手段。一个类的友员可以访问该类各种性质的成员。问该类各种性质的成员。从编译器的观点看,类是一个程序包。定义什么类成员和从编译器的观点看,类是一个程序包。定义什么类成员和如何声明成员的访问性质,取决于问题的需要。如何声明成员的访问性质,取决于问题的需要。Object Oriented继承是面向对象程序设计实现软件重用的重要方法。程序继承是面向对象程序设计实现软件重用的重要方法。程序员可以在已有类的基础上定义新

104、的数据成员和成员函数。员可以在已有类的基础上定义新的数据成员和成员函数。原有类称为基类,新的类称为派生类,这种程序设计方原有类称为基类,新的类称为派生类,这种程序设计方法称为继承。法称为继承。派生类成员由基类成员和自身定义的成员组成。单继承的派生类成员由基类成员和自身定义的成员组成。单继承的派生类只有一个基类。多继承的派生类有多个基类。派生类只有一个基类。多继承的派生类有多个基类。对基类成员的访问性质受继承方式影响。对基类成员的访问性质受继承方式影响。公有(公有(publicpublic)继承方式,基类的)继承方式,基类的publicpublic和和protectedprotected成员在派

105、生类中性质不变;成员在派生类中性质不变;保护(保护(protectedprotected)继承,基类的)继承,基类的publicpublic和和protectedprotected成员都成为派生类的成员都成为派生类的protectedprotected成员;成员;私有(私有(privateprivate)继承,基类的)继承,基类的publicpublic和和protectedprotected成成员都成为派生类的员都成为派生类的privateprivate成员。成员。Object Oriented派生类中不可见基类的私有数据成员,但这些数据存储单派生类中不可见基类的私有数据成员,但这些数据存储

106、单元依然被建立。创建派生类对象时,派生类的构造函数总元依然被建立。创建派生类对象时,派生类的构造函数总是先调用基类构造函数来初始化派生类中的基类成员。调是先调用基类构造函数来初始化派生类中的基类成员。调用基类构造函数可以通过初始化列表实现数据成员的初始用基类构造函数可以通过初始化列表实现数据成员的初始化。调用析构函数的次序和调用构造函数的次序相反。化。调用析构函数的次序和调用构造函数的次序相反。类继承关系中,覆盖成员出现访问的二义性,可以用作用类继承关系中,覆盖成员出现访问的二义性,可以用作用域符显示指定类成员。域符显示指定类成员。为了避免多继承类格中的汇点类在派生类对象中产生不同为了避免多继

107、承类格中的汇点类在派生类对象中产生不同副本,副本,C+C+提供虚继承机制。提供虚继承机制。多继承提供了软件重用的强大功能,也增加了程序的复杂多继承提供了软件重用的强大功能,也增加了程序的复杂性。性。Object Oriented虚函数和多态性使软件设计易于扩充。虚函数和多态性使软件设计易于扩充。冠以关键字冠以关键字virtualvirtual的成员函数称为虚函数。派生类可以重的成员函数称为虚函数。派生类可以重载基类的虚函数,只要接口相同,函数的虚特性不变。载基类的虚函数,只要接口相同,函数的虚特性不变。基类指针可以指向派生类对象;以及基类中拥有虚函数,基类指针可以指向派生类对象;以及基类中拥有

108、虚函数,是支持多态性的前提。当通过基类指针或引用使用虚函数是支持多态性的前提。当通过基类指针或引用使用虚函数时,时,C+C+在程序运行时根据所指对象类型在类层次中正确选在程序运行时根据所指对象类型在类层次中正确选择重定义的函数。这种运行时的晚期匹配称为动态联编。择重定义的函数。这种运行时的晚期匹配称为动态联编。如果通过对象名和点运算符方式调用虚函数,则调用关联如果通过对象名和点运算符方式调用虚函数,则调用关联在编译时由引用对象的类型确定,称为静态联编。在编译时由引用对象的类型确定,称为静态联编。如果一个基类中包含虚函数,通常把它的析构函数说明为如果一个基类中包含虚函数,通常把它的析构函数说明为

109、虚析构函数。这样,它的所有派生类析构函数也自动成为虚析构函数。这样,它的所有派生类析构函数也自动成为虚析构函数(即使它们与基类析构函数名字不相同)。虚虚析构函数(即使它们与基类析构函数名字不相同)。虚析构函数使得用析构函数使得用deletedelete算符删除对象时,系统可以正确地算符删除对象时,系统可以正确地调用析构函数。调用析构函数。Object Oriented纯虚函数是在说明时代码纯虚函数是在说明时代码“初始化值初始化值”为为0 0的虚函数。纯虚的虚函数。纯虚函数本身没有实现,由它的派生类定义实现版本。函数本身没有实现,由它的派生类定义实现版本。具有纯虚函数的类称为抽象类。抽象类只能作

110、为基类,不具有纯虚函数的类称为抽象类。抽象类只能作为基类,不能建立实例化对象。如果抽象类的派生类不提供纯虚函数能建立实例化对象。如果抽象类的派生类不提供纯虚函数的实现,则它依然是抽象类。定义了纯虚函数实现的派生的实现,则它依然是抽象类。定义了纯虚函数实现的派生类,即可以建立对象的类称为具体类。类,即可以建立对象的类称为具体类。尽管不能建立抽象类对象,但抽象类机制提供的软件抽象尽管不能建立抽象类对象,但抽象类机制提供的软件抽象和可扩展性的手段;抽象类指针使得派生的具体类对象具和可扩展性的手段;抽象类指针使得派生的具体类对象具有多态操作能力。异质链表是多态应用的一个实例。有多态操作能力。异质链表是

111、多态应用的一个实例。Object Oriented运算符重载的作用是令用户可以像操作基本数据类型一样,运算符重载的作用是令用户可以像操作基本数据类型一样,用简洁明确的运算符操作自定义的类对象。程序设计中,用简洁明确的运算符操作自定义的类对象。程序设计中,运算符重载主要用于数学类模仿运算符的习惯用法。运算符重载主要用于数学类模仿运算符的习惯用法。C+C+语言中大部分预定义的运算符都可以被重载。重载运算语言中大部分预定义的运算符都可以被重载。重载运算符函数可以对运算符做出新的解释,定义用户所需要的各符函数可以对运算符做出新的解释,定义用户所需要的各种操作,但重载后原有的基本语义,包括运算符的优先级

112、、种操作,但重载后原有的基本语义,包括运算符的优先级、结合性和所需要是操作数不变。结合性和所需要是操作数不变。运算符函数既可以重载为成员函数,也可以重载为友员函运算符函数既可以重载为成员函数,也可以重载为友员函数或普通函数。数或普通函数。当一元运算符的操作数,或者二元运算符的左操作数是当一元运算符的操作数,或者二元运算符的左操作数是该类的一个对象时,以成员函数重载;该类的一个对象时,以成员函数重载;友员函数重载运算符常用于算符的左右操作数类型不同友员函数重载运算符常用于算符的左右操作数类型不同友员函数重载运算符常用于算符的左右操作数类型不同友员函数重载运算符常用于算符的左右操作数类型不同的情况

113、,左操作数可以是常数或其他类型的数。的情况,左操作数可以是常数或其他类型的数。的情况,左操作数可以是常数或其他类型的数。的情况,左操作数可以是常数或其他类型的数。Object Oriented运行结果运行结果运行结果运行结果1 1#includeclassTpublic:T(intx)a=x;b+=x;staticvoiddisplay(Tc)couta=c.atb=c.bendl;private:inta;staticintb;intT:b=5;voidmain()TA(3),B(5);T:display(A);T:display(B);Object Oriented运行结果运行结果运行结果

114、运行结果2 2#include#includeclasspointpublic:point(floatx,floaty)a=x;b=y;?cout“点点(”a“,”b“)”;frienddoubled(point&A,point&B);private:doublea,b;doubled(point&A,point&B)returnsqrt(A.a-B.a)*(A.a-B.a)+(A.b-B.b)*(A.b-B.b);voidmain()pointp1(2,3);cout到到;pointp2(4,5);cout的距离是:的距离是:d(p1,p2)endl;Object Oriented运行结果运

115、行结果运行结果运行结果3 3#includeclassApublic:A()a=5;voidprinta()coutA:a=aendl;private:inta;friendclassB;classBpublic:voiddisplay1(At)t.a+;coutdisplay1:a=t.aendl;voiddisplay2(At)t.a-;coutdisplay2:a=t.aendl;voidmain()Aobj1;Bobj2;obj1.printa();obj2.display1(obj1);obj2.display2(obj1);obj1.printa();Object Oriented

116、运行结果运行结果运行结果运行结果4 4#includeclassBase1public:Base1(inti)cout调用基类调用基类Base1的构造函数的构造函数:iendl;classBase2public:Base2(intj)cout调用基类调用基类Base2的构造函数的构造函数:jendl;classA:publicBase1,publicBase2public:A(inta,intb,intc,intd):Base2(b),Base1(c),b2(a),b1(d)cout调用派生类调用派生类A的构造函数的构造函数:a+b+c+dendl;private:Base1b1;Base2b

117、2;voidmain()Aobj(1,2,3,4);Object Oriented运行结果运行结果运行结果运行结果5 5#includeclassBclasspublic:Bclass(inti,intj)x=i;y=j;virtualintfun()return0;protected:intx,y;classIclass:publicBclasspublic:Iclass(inti,intj,intk):Bclass(i,j)z=k;intfun()return(x+y+z)/3;private:intz;voidmain()Iclassobj(2,4,10);Bclassp1=obj;co

118、utp1.fun()endl;Bclass&p2=obj;coutp2.fun()endl;coutp2.Bclass:fun()endl;Bclass*p3=&obj;coutfun()endl;Object Oriented编程编程编程编程1 1定义一个定义一个StudentStudent类,在该类定义中包括:类,在该类定义中包括: 一个数据成员一个数据成员scorescore(分数)及两个静态数据成员(分数)及两个静态数据成员totaltotal(总分)和学生人数(总分)和学生人数countcount; 成员函数成员函数scoretotalcount(floatscoretotalcou

119、nt(float s) s) 用于设置分用于设置分数、求总分和累计学生人数;数、求总分和累计学生人数; 静态成员函数静态成员函数sum()sum()用于返回总分;用于返回总分; 静态成员函数静态成员函数average()average()用于求平均值。用于求平均值。在在 mainmain函数中,输入某班同学的成绩,并调用上函数中,输入某班同学的成绩,并调用上述函数求全班学生的总分和平均分。述函数求全班学生的总分和平均分。Object Oriented#includeclassstudentpublic:voidscoretotalcount(floats)score=s;total=total

120、+score;count+;staticfloatsum()returntotal;staticfloataverage()returntotal/count;private:floatscore;staticfloattotal;staticfloatcount;floatstudent:total=0;floatstudent:count=0;Object Orientedvoidmain()inti,n;floats;coutn;studentstu;for(i=1;i=n;i+)cout请输入第请输入第is;stu.scoretotalcount(s);cout总分:总分:studen

121、t:sum()endl;cout平均分:平均分:student:average()endl;Object Oriented编程编程编程编程2 2某商店经销一种货物。货物购进和卖出时以箱为单某商店经销一种货物。货物购进和卖出时以箱为单位,各箱的重量不一样,因此,商店需要记录目前位,各箱的重量不一样,因此,商店需要记录目前库存的总重量。现在用库存的总重量。现在用C+C+模拟商店货物购进和卖模拟商店货物购进和卖出的情况。出的情况。 Object Oriented#includeclassGoodspublic:Goods(intw)weight=w;total_weight+=w;/构造函数购进货物

122、Goods()total_weight-=weight;/析造函数售出货物intWeight()returnweight;staticintTotalWeight()returntotal_weight;/静态成员函数返回货物总重量Goods*next;/用于构造链表的类指针private:intweight;staticinttotal_weight;intGoods:total_weight=0;/静态数据成员记录货物总重量Object Orientedvoidpurchase(Goods*&f,Goods*&r,intw)Goods*p=newGoods(w);p-next=NULL;i

123、f(f=NULL)f=r=p;elser-next=p;r=r-next;voidsale(Goods*&f,Goods*&r)if(f=NULL)coutnext;deleteq;coutsaled.n;front 98 170 31 50rearfr200w200 p349total_weightObject Orientedvoidmain()Goods*front=NULL,*rear=NULL;intw;intchoice;docoutPleasechoice:n;coutchoice;switch(choice)/ 操作选择操作选择case1:/ 键入键入1,购进,购进1箱货物箱货

124、物coutw;purchase(front,rear,w);/ 从表尾插入从表尾插入1个结点个结点break;case2:/ 键入键入2,售出,售出1箱货物箱货物sale(front,rear);break;/ 从表头删除从表头删除1个结点个结点case0:break;/ 键入键入0,结束,结束coutNowtotalweightis:Goods:TotalWeight()endl;while(choice);Object Oriented作业作业作业作业1 1定义一个表示点的结构类型定义一个表示点的结构类型PointPoint和一个由直线方程和一个由直线方程y = ax y = ax + b

125、+ b确定的直线类确定的直线类LineLine。结构类型结构类型PointPoint有有x x和和y y两个成员,分别表示点的横坐标和纵两个成员,分别表示点的横坐标和纵坐标。坐标。LineLine类有两个数据成员类有两个数据成员a a和和b b,分别表示直线方程中的系数,分别表示直线方程中的系数a a和和b b。LineLine类有一个成员函数类有一个成员函数printprint用于显示直线方程;用于显示直线方程;友员函数友员函数setPoint(LinesetPoint(Line &l1,Line &l2) &l1,Line &l2)用于求两条直线的用于求两条直线的交点。交点。在在mainm

126、ain函数中,建立两个直线对象,分别调用函数中,建立两个直线对象,分别调用printprint函数显函数显示两条直线的方程,并调用函数示两条直线的方程,并调用函数setPointsetPoint求这两条直线的求这两条直线的交点。交点。 Object Oriented作业作业作业作业2 2某学校对教师每月工资的计算规定如下:固定工资某学校对教师每月工资的计算规定如下:固定工资+ +课时补课时补贴。贴。教授的固定工资为教授的固定工资为50005000元,每个课时补贴元,每个课时补贴5050元。元。副教授的固定工资为副教授的固定工资为30003000元,每个课时补贴元,每个课时补贴3030元。元。讲师的固定工资为讲师的固定工资为20002000元,每个课时补贴元,每个课时补贴2020元。元。定义教师抽象类,派生不同职称的教师类,编写程序求若定义教师抽象类,派生不同职称的教师类,编写程序求若干个教师的月工资。干个教师的月工资。Object Oriented

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号