c++第四讲 类与对象PPT课件_第1页
c++第四讲 类与对象PPT课件_第2页
c++第四讲 类与对象PPT课件_第3页
c++第四讲 类与对象PPT课件_第4页
c++第四讲 类与对象PPT课件_第5页
已阅读5页,还剩138页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第四章类与对象,主讲人:kehua电子邮件:联系电话:,说明:本章课件糅合了胡彬老师,李战春老师和吴乃陵的课件;教材中不讲的内容基本去掉了;但是页数仍然较多,提供了一些素材,各位老师各取所需吧。,2020/5/21,计算机基础教研室,2,类与对象,本章重点C+中的类对象的概念构造函数析构函数,2020/5/21,计算机基础教研室,3,蝶变在蛰伏中向更好或更完美的方面极大蜕变,类似于毛虫在蛹中完成成为蝴蝶的过程,破茧的一刹那就是蝶变了。蝶变又称蜕变。,2020/5/21,计算机基础教研室,4,回顾:面向过程的设计方法,重点:如何实现细节过程,将数据与函数分开。形式:主模块+若干个子模块(main()+子函数)。模块化是按功能来分的,所以也称功能块。在C+中称为一个函数,一个函数解决一个问题,即实现一个功能或一个操作。功能块独立性要强(模块内部的联系要紧密,模块间的联系要弱),2020/5/21,计算机基础教研室,5,回顾:面向过程的设计方法,思想特点:(正确有效的!)自顶向下,逐步求精功能分解。缺点:效率低,程序的可重用性差。全局变量会加强模块间的联系,对以功能抽象为基础的结构化程序设计,当程序规模和复杂性达到一定程度时,不可避免地会引入大量的全局变量。面向过程程序设计缺点的根源在于数据与数据处理分离。,2020/5/21,计算机基础教研室,6,面向对象的方法,目的:实现软件设计的产业化。观点:自然界是由实体(对象)所组成。程序设计方法:使用面向对象的观点来描述模仿并处理现实问题。面向对象技术中的对象就是现实世界中某个具体的物理实体在计算机世界中的映射和体现。要求:高度概括、分类、和抽象。,2020/5/21,计算机基础教研室,7,对象,类,计算机世界,实体,抽象类别,现实世界客观世界,抽象,抽象,实例化,映射,主观世界,对象、实体与类,现实世界中的实体可以抽象出类别的概念。对应于计算机世界就有一个类(class)的概念。面向对象就是计算机世界模拟现实世界。,现实世界与计算机世界的映射关系,2020/5/21,计算机基础教研室,8,面向对象编程,2020/5/21,计算机基础教研室,9,对象,“对象是存在的具体实体,具有明确定义的状态和行为。”,2020/5/21,计算机基础教研室,10,对象的示例,收银员对象,顾客对象,顾客姓名:朱丽叶年龄:28体重:52千克操作:购买商品,状态,姓名:布兰尼职衔:收银员年龄:35体重:60千克操作:收款打印帐单,行为,2020/5/21,计算机基础教研室,11,消息传递,“消息指一个对象为执行某项特定操作而向另一个对象发送的请求”,2020/5/21,计算机基础教研室,12,类,类以共同特性和操作定义实体类是用于组合各个对象所共有操作和属性的一种机制,形状类,动物类,汽车类,类的示例,“类是具有相同属性和行为的一组对象的集合”类是一个抽象的概念,用来描述该类对象所共有的本质的属性和行为。,2020/5/21,计算机基础教研室,13,类和对象的示例,促销员,采购经理,收银员,系统管理员,仓库管理员,2020/5/21,计算机基础教研室,14,属性,事物的特性在类中表示为变量每个对象的每个属性都拥有其特有的值属性名称由类的所有实例共享,住址,姓名,属性,年龄,“在类中表示对象或实体拥有的特性时称为属性”,2020/5/21,计算机基础教研室,15,方法,“对象执行的操作称为方法。”,2020/5/21,计算机基础教研室,16,方法的示例,缝衣服的步骤,量尺寸,得到工具,缝衣服,方法,缝制衣服,裁缝,2020/5/21,计算机基础教研室,17,类和对象的区别,类是概念模型,定义对象的所有特性和所需的操作,对象是真实的模型,类定义实体,对象是实际的实体,2020/5/21,计算机基础教研室,18,抽象,处理事物复杂性的方法,只关注事物的重要细节,而忽略事物的次要细节。,2020/5/21,计算机基础教研室,19,数据抽象,抽取出关键数据抽取出属性和方法,“根据具体的应用抽取出类的相关属性和操作。”,2020/5/21,计算机基础教研室,20,数据抽象的示例,属性,方法,getName(),getStudentNO(),getSeatNumber(),2020/5/21,计算机基础教研室,21,封装,信息隐藏,隐藏对象的实现细节,不让用户看到将东西包装在一起,然后以新的完整形式呈现出来例如,两种或多种化学药品组成一个胶囊将方法和属性一起包装到一个单元中,单元以类的形式实现,“隐藏属性、方法或实现细节的过程称为封装。”,2020/5/21,计算机基础教研室,22,封装的示例3-1,接口,采购经理,罗杰斯先生,法拉力公司,.,迪斯尼汽车公司,.,市场经理,雪莉女士,要求,2020/5/21,计算机基础教研室,23,封装的示例3-2,有选择地提供数据,法拉力公司,迪斯尼汽车公司,2020/5/21,计算机基础教研室,24,封装的示例3-3,实体法拉力公司,实体迪斯尼汽车公司,AutiLtd,.,ButoLtd,.,2020/5/21,计算机基础教研室,25,继承与派生,是C+中支持层次分类的一种机制,允许程序员在保持原有类特性的基础上,进行更具体的说明。,2020/5/21,计算机基础教研室,26,多态性,语文、数学、英语、政治、物理、化学、生物,高中生,计算平均成绩,大学生,高数、英语、计算机、线性代数,多态:主要用于具有继承关系的类体系中,一个类体系中的不同对象可以用不同方式响应同一个消息,并产生不同结果,实现“同一接口,多种方法”,同一名称,不同的功能实现方式。目的:达到行为标识统一,减少程序中标识符的个数。,2020/5/21,计算机基础教研室,27,结构化程序与面向对象程序的比较,问题:输入圆的半径,求圆的周长和面积数据描述:半径,周长,面积均用实型数表示数据处理:输入半径r;计算周长=2*r;计算面积=*r2;输出半径,周长,面积;,2020/5/21,计算机基础教研室,28,方法一:用结构化方法编程,求圆的周长和面积,#includeusingnamespacestd;voidmain()doubler,girth,area;constdoublePI=3.1415;coutr;girth=2*PI*r;area=PI*r*r;coutradius=rendl;coutgirth=girthendl;coutarea=areaendl;,2020/5/21,计算机基础教研室,29,方法二:用面向对象方法编程,求圆的周长和面积,实例化,分析,“圆”是抽象的类类型,建立具体的圆(对象),半径?,圆的周长?面积?,2020/5/21,计算机基础教研室,30,方法二:用面向对象方法编程,求圆的周长和面积,实例化,分析,圆类数据成员半径成员函数置半径值求圆的半径求周长求面积,2020/5/21,计算机基础教研室,31,方法二:用面向对象方法编程,求圆的周长和面积,#includeusingnamespacestd;classCircledoubleradius;public:voidSet_Radius(doubler)radius=r;doubleGet_Radius()returnradius;doubleGet_Girth()return2*3.14*radius;doubleGet_Area()return3.14*radius*radius;voidmain()CircleA,B;A.Set_Radius(6.23);coutA.Radius=A.Get_Radius()endl;coutA.Girth=A.Get_Girth()endl;coutA.Area=A.Get_Area()endl;B.Set_Radius(10.5);coutB.radius=B.Get_Radius()endl;coutB.Girth=B.Get_Girth()endl;coutB.Area=B.Get_Area()endl;,Circle类定义,数据成员,成员函数,建立对象(类类型变量),通过对象调用类的成员函数,2020/5/21,计算机基础教研室,32,类与对象的基本概念,4.1.3对象的创建与使用,4.1.1C+类的定义,4.1.2成员函数的定义,2020/5/21,计算机基础教研室,33,类的引入:类是一种数据类型。描述客观事物必须用不同的数据类型来描述不同的方面。如商品:商品名称(用字符串描述),该商品数量(用整型数描述),该商品单价(用浮点数描述),该商品总价(用浮点数描述)。这里用了属于三种不同数据类型的四个数据成员(datamember)来描述一种商品。,C+类的定义,2020/5/21,计算机基础教研室,34,classCGoodspublic:charName21;intAmount;floatPrice;floatTotal_value;/最后的分号不可少,这是一条说明语句关键字class是数据类型说明符,指出下面说明的是类。标识符CGoods是商品这个类的类型名。花括号中是构成类体的系列成员,关键字public是一种访问限定符。,C+类的定义,2020/5/21,计算机基础教研室,35,访问限定符(accessspecifier):public(公共的)说明的成员能从外部进行访问。何为内外?内外有别!private(私有的)和protected(保护的)说明的成员不能从外部进行访问。每种说明符可在类体中使用多次。访问限定符的作用域是从该说明符出现开始到下一个说明符之前或类体结束之前结束。如果在类体起始点无访问说明符,系统默认定义为私有(private)。访问限定符private(私有的)和protected(保护的)体现了类具有封装性(Encapsulation)。,C+类的定义,2020/5/21,计算机基础教研室,36,class类名private:成员表1;public:成员表2;protected:成员表3;/注意:所有说明都以分号结束其中“class类名”称为类头(classhead)。花括号中的部分称为类体(classbody),类体中定义了类成员表(classmemberlist),包含数据和函数。,C+类的定义,2020/5/21,计算机基础教研室,37,classCGoodsprivate:charName21;intAmount;floatPrice;floatTotal_value;public:voidRegisterGoods(char,int,float);/输入数据voidCountTotal();/计算商品总价值voidGetName(char);/读取商品名intGetAmount();/读取商品数量floatGetPrice();/读取商品单价floatGetTotal_value();/读取商品总价值;,C+类的定义,成员函数,2020/5/21,计算机基础教研室,38,封装:类把数据(事物的属性)和函数(事物的行为操作)封装为一个整体。接口:通常数据成员被说明成私有的,函数成员被说明成公有的;从外部对数据成员进行操作,只能通过公有函数来完成,数据受到了良好的保护,不易受副作用的影响。公有函数集定义了类的接口(interface)。成员函数可以直接使用类定义中的任一成员,可以处理数据成员,也可调用函数成员。注意:类是一种数据类型,定义时系统不为类分配存储空间,所以不能对类的数据成员初始化。类中的任何数据成员也不能使用关键字extern、auto或register限定其存储类型。,2020/5/21,计算机基础教研室,39,通常在类定义中,成员函数仅作声明。函数定义通常在类的说明之后进行,其格式如下:返回值类型类名:函数名(参数表)/函数体其中运算符“:”称为作用域解析运算符(scoperesolutionoperator),它指出该函数是属于哪一个类的成员函数。,成员函数的定义,;,2020/5/21,计算机基础教研室,40,类CGoods函数的定义,voidCGoods:RegisterGoods(charname,intamount,floatprice)strcpy(Name,name);/字符串复制函数Amount=amount;Price=price;voidCGoods:CountTotal(void)Total_value=Price*Amount;voidCGoods:GetName(charname)strcpy(name,Name);intCGoods:GetAmount(void)return(Amount);floatCGoods:GetPrice(void)return(Price);floatCGoods:GetTotal_value(void)return(Total_value);,2020/5/21,计算机基础教研室,41,定义对象:对象是类的实例(instance)。定义一种数据类型只是告诉编译系统该数据类型的构造,并没有预定内存。类只是一个样板,以此样板可以在内存中开辟出同样结构的实例对象。格式如下:CGoodsCar;这个定义创建了CGoods类的一个对象Car,同时为它分配了属于它自己的存储块,用来存放数据和对这些数据实施操作的成员函数(代码)。对象只在定义它的域中有效。,对象的创建与使用,2020/5/21,计算机基础教研室,42,对象存储:,图4.1各对象完全独立地安排内存的方案,图4.1是系统为每一个对象分配了全套的内存。数据区安放成员数据,代码区安放成员函数。注意:区别同一个类的各个不同的对象的属性是由数据成员决定的,不同对象的数据成员的内容是不一样的;而行为(操作)是用函数来描述的,这些操作的代码对所有对象都是一样的。,2020/5/21,计算机基础教研室,43,图4.2各对象的代码区共用的方案,图4.2仅为每个对象分配一个数据区,代码区(放成员函数的区域)为各对象类共用。图4.1对应的是在类说明中定义函数,而图4.2对应的是在类说明外部定义函数。,this指针妙传,形实结合,2020/5/21,计算机基础教研室,44,内联函数:使用关键字inline,系统自动采用内联扩展方法实现,每个对象都有该函数一份独立的代码。如RegisterGoods()函数可定义为:inlinevoidCGoods:RegisterGoods(charname,intamount,floatprice)strcpy(Name,name);Amount=amount;Price=price;则每个对象都有RegisterGoods()函数一份独立的代码。注意:inline只是一个建议,最后由编译器决定是否执行。对象的存储方式是物理的,这是由计算机来完成的,它并不影响类在逻辑上的封装性。程序设计是一个逻辑的概念。,2020/5/21,计算机基础教研室,45,回顾用面向对象方法编程,求圆的周长和面积,分析,“圆”是抽象的类类型,建立具体的圆(对象),半径?,圆的周长?面积?,实例化,2020/5/21,计算机基础教研室,46,分析,圆类数据成员半径成员函数置半径值求圆的半径求周长求面积,实例化,回顾用面向对象方法编程,求圆的周长和面积,2020/5/21,计算机基础教研室,47,#includeusingnamespacestd;classCircledoubleradius;public:voidSet_Radius(doubler);doubleGet_Radius();doubleGet_Girth();doubleGet_Area();,Circle类定义,数据成员,成员函数,回顾用面向对象方法编程,求圆的周长和面积,2020/5/21,计算机基础教研室,48,voidCircle:Set_Radius(doubler)radius=r;doubleCircle:Get_Radius()returnradius;doubleCircle:Get_Girth()return2*3.14f*radius;doubleCircle:Get_Area()return3.14f*radius*radius;,各对象的代码区共用的方案,回顾用面向对象方法编程,求圆的周长和面积,2020/5/21,计算机基础教研室,49,voidmain()CircleA,B;A.Set_Radius(6.23);coutA.Radius=A.Get_Radius()endl;coutA.Girth=A.Get_Girth()endl;coutA.Area=A.Get_Area()endl;B.Set_Radius(10.5);coutB.radius=B.Get_Radius()endl;coutB.Girth=B.Get_Girth()endl;coutB.Area=B.Get_Area()endl;,建立对象(类类型变量),通过对象调用类的成员函数,回顾用面向对象方法编程,求圆的周长和面积,2020/5/21,计算机基础教研室,50,#includeusingnamespacestd;classCircledoubleradius;public:voidSet_Radius(doubler)radius=r;doubleGet_Radius()returnradius;doubleGet_Girth()return2*3.14f*radius;doubleGet_Area()return3.14f*radius*radius;,为每一个对象分配了全套的内存,回顾用面向对象方法编程,求圆的周长和面积,2020/5/21,计算机基础教研室,51,数据成员多为私有的,要对它们进行初始化,必须用一个公有函数来进行。同时这个函数应该在且仅在定义对象时自动执行一次。称为:构造函数(constructor),4.3.1构造函数的定义与使用,4.3.2析构函数的定义与使用,构造函数与析构函数,2020/5/21,计算机基础教研室,52,构造函数由于类的封装性,不能象普通变量一样初始化。构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。在对象创建时由系统自动调用。如果程序中未声明,则系统自动产生出一个默认形式的构造函数。允许为内联函数、重载函数、带默认形参值的函数。,构造函数的定义与使用,2020/5/21,计算机基础教研室,53,1.函数名与类名相同。2.构造函数无函数返回类型说明。注意是什么也不写,也不可写void!隐式自动调用一次3.在程序运行时,当新的对象被建立,该对象所属的类的构造函数自动被调用,在该对象生存期中也只调用这一次。4.构造函数可以重载。严格地讲,说明中可以有多个构造函数,它们由不同的参数表区分,系统在自动调用时按一般函数重载的规则选一个执行。,构造函数的特征,2020/5/21,计算机基础教研室,54,5.构造函数可以在类中定义,也可以在类外定义。6.如果类说明中没有给出构造函数,则C+编译器自动给出一个默认的构造函数:类名()但只要我们定义了一个构造函数,系统就不会自动生成默认的构造函数。只要构造函数是无参的或各参数均有默认值的,C+编译器都认为是默认的构造函数,并且默认的构造函数只能有一个。,构造函数的特征,2020/5/21,计算机基础教研室,55,析构函数(destructor)特征:当一个对象的生命周期结束时,C+会自动调用析构函数(destructor)对该对象并进行善后工作,1.构函数名与类名相同,但在前面加上字符,如CGoods()。2.析构函数无函数返回类型,与构造函数在这方面是一样的。但析构函数不带任何参数。3.一个类有一个也只有一个析构函数,这与构造函数不同。析构函数可以默认。4.对象注销时,系统自动调用析构函数。,析构函数的定义与使用,2020/5/21,计算机基础教研室,56,#includeusingnamespacestd;classQintx,y;public:Q(inta=0,intb=0)cout“调用了构造函数”endl;x=a;y=b;voidP(void)coutxtyn;Q()cout“调用了析构函数!”n;,voidmain(void)Qq(50,100);q.P();coutradius;/声明Circle对象CirclePool(radius);CirclePoolRim(radius+3);/计算栅栏造价并输出FenceCost=PoolRim.Circumference()*FencePrice;coutFencingCostis¥FenceCostendl;/计算过道造价并输出ConcreteCost=(PoolRim.Area()-Pool.Area()*ConcretePrice;coutConcreteCostis¥ConcreteCostendl;,运行结果:Entertheradiusofthepool:10FencingCostis¥2858.85ConcreteCostis¥4335.3,2020/5/21,计算机基础教研室,60,【例4.2】矩形类。要确定一个矩形(四边都是水平或垂直方向,不能倾斜),只要确定其左上角和右下角的x和y坐标即可,即左右上下四个边界值。并用多文件实现。classRectangleintleft,top,right,bottom;public:Rectangle(int=0,int=0,int=0,int=0);/默认构造函数必须在此指定默认实参Rectangle();/析构函数,在此函数体为空voidAssign(int,int,int,int);voidSetLeft(intt)left=t;voidSetRight(intt)right=t;voidSetTop(intt)top=t;voidSetBottom(intt)bottom=t;voidShow();/将上述内容保存为rect.h,2020/5/21,计算机基础教研室,61,#include#includerect.husingnamespacestd;Rectangle:Rectangle(intl,intt,intr,intb)left=l;top=t;right=r;bottom=b;voidRectangle:Assign(intl,intt,intr,intb)left=l;top=t;right=r;bottom=b;voidRectangle:Show()cout”left-toppointis(”left”,”top”)”n;cout”right-bottompointis(”right”,”bottom”)”n;/将上述内容保存为rect.cpp,2020/5/21,计算机基础教研室,62,#includeusingnamespacestd;#include“rect.h”intmain()Rectanglerect;rect.Show();rect.Assign(100,200,300,400);rect.Show();Rectanglerect1(0,0,200,200);rect1.Show();Rectanglerect2(rect1);rect2.Show();return0;/将上述内容保存为Exp10_1.cpp,2020/5/21,计算机基础教研室,63,4.4.1引用,4.4.2复制构造函数,4.4.3成员对象与构造函数,引用与复制构造函数,2020/5/21,计算机基础教研室,64,引用的导入:参数传递的传值方式在函数域中为参数重新分配内存,而把实参的数值传递到新分配的内存中。它的优点是有效避免函数的副作用。问题:如果要求改变实参的值,怎么办呢?如果实参是一个复杂的对象,重新分配内存会引起程序执行效率大大下降,怎么办呢?有一种导出型数据类型引用(reference)可以解决上面的难题。引用又称别名(alias)。,引用,2020/5/21,计算机基础教研室,65,引用的定义:引用是给一个已经定义的变量重新起一个别名,而不是定义一个新的变量,定义的格式为:类型newnum是新定义的引用类型变量,它是变量number的别名。引用主要用于函数之间的数据传递。,引用,2020/5/21,计算机基础教研室,66,newnum是变量number的别名,C+系统不为引用类型变量分配内存空间。内存分配见下图:,number称为引用newnum的关联变量。“/全局变量doublefsqr1(doublea)temp=a*a;returntemp;double运行结果为:x=30.25y=30.25运行结果一样,但在内存中的活动却不同。,【例4.4】引用作为函数的返回值,2020/5/21,计算机基础教研室,70,图4.6普通返回,图4.7引用返回,图4.6所示的情况,函数fsqr1返回表达式全局变量temp的值,所以是将temp的值赋值给那个无名临时变量,回到主函数后,赋值表达式x=fsqr1(5.5)把临时变量的值赋给x,无名临时变量生命期结束。,图4.7所示情况,没有使用那个无名临时变量过渡,而是直接返回temp本身,赋给y。无名临时变量中放的是temp的地址。不产生副本,效率提高了。但返回值不再是表达式。,2020/5/21,计算机基础教研室,71,【例4.5】返回值为引用的函数作为左值(选读),【例4.5】统计学生成绩,分数在80分以上的为A类,60分以上,80分以下的为B类,60分以下为C类。int,2020/5/21,计算机基础教研室,72,同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制是完全可行的。这个复制过程只需要复制数据成员,而函数成员是共用的(没有复制)。在建立对象时可用同一类的另一个对象来初始化该对象,这时所用的构造函数称为复制(拷贝)构造函数(CopyConstructor)。,复制(拷贝)构造函数,2020/5/21,计算机基础教研室,73,classClockpublic:voidSetTime(intNewH,intNewM,intNewS);voidShowTime();private:intHour,Minute,Second;Clocka;Clockb=a;,错误?,复制构造函数的引入,2020/5/21,计算机基础教研室,74,复制构造函数是一种特殊的构造函数,其形参为本类的对象引用。作用:使用一个对象(参数指定的对象),去初始化一个正在被建立的同类型对象。class类名public:类名(形参);/构造函数类名(类名/调用三个参数的构造函数CGoodCar2=Car1;/调用复制构造函数CGoodCar3(Car1);/调用复制构造函数,Car1为实参这样三个对象的初始化结果完全一样。,注意:在类定义中如果没有显式给出构造函数时,并不是不用构造函数,而是由系统自动调用默认的构造函数或默认的复制构造函数。如果有程序设计者定义的构造函数(包括复制构造函数),则按函数重载的规律,调用合适的构造函数。,复制构造函数,2020/5/21,计算机基础教研室,77,classPointpublic:Point(intxx=0,intyy=0)X=xx;Y=yy;Point(Point,复制构造函数举例,2020/5/21,计算机基础教研室,78,(1)当用类的一个对象去初始化该类的另一个对象时系统自动调用复制构造函数实现拷贝赋值。voidmain(void)PointA(1,2);PointB(A);/复制构造函数被调用coutB.GetX()endl;,复制构造函数调用的三种情况,2020/5/21,计算机基础教研室,79,(2)若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用复制构造函数。例如:voidfun1(Pointp)coutp.GetX()endl;voidmain()PointA(1,2);fun1(A);/调用复制构造函数,复制构造函数调用的三种情况,2020/5/21,计算机基础教研室,80,(3)当函数的返回值是类对象时,系统自动调用复制构造函数。例如:Pointfun2()PointA(1,2);returnA;/调用复制构造函数voidmain()PointB;B=fun2();,复制构造函数调用的三种情况,2020/5/21,计算机基础教研室,81,如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数。这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。,复制构造函数,2020/5/21,计算机基础教研室,82,聚合(aggregation):类中的成员,除了成员数据和成员函数外,还有成员对象,即用其他类的对象作为类的成员。使用成员对象的技术称为聚合。成员对象是实体,系统不仅为它分配内存,而且要进行初始化。,成员对象与构造函数,2020/5/21,计算机基础教研室,83,原则:不仅要负责对本类中的基本类型成员数据赋初值,也要对对象成员初始化。声明形式:类名:类名(对象成员所需的形参,本类成员形参):对象1(参数表),对象2(参数表),.本类初始化,含对象成员的构造函数,2020/5/21,计算机基础教研室,84,classPointprivate:floatx,y;/点的坐标public:Point(floatxx,floatyy);/构造函数floatGetX(void)returnx;/取X坐标floatGetY(void)returny;/取Y坐标;,类组合构造函数实例,2020/5/21,计算机基础教研室,85,classLineprivate:/线段的两个端点Pointp1,p2;doubles;public:/构造函数Line(Pointa,Pointb);/如何写?;,类组合构造函数实例,2020/5/21,计算机基础教研室,86,Line:Line(Pointa,Pointb):p1(a),p2(b)doublex=double(p1.GetX()-p2.GetX();doubley=double(p1.GetY()-p2.GetY();doubledist=sqrt(x*x+y*y);s=dist;,类组合构造函数实例,2020/5/21,计算机基础教研室,87,含对象成员的析构函数:因为析构函数没有参数,所以包含成员对象的类的析构函数形式上并无特殊之处。但是撤销该类对象时,会首先调用自己的析构函数,再调用成员对象的析构函数,调用次序与初始化时的次序相反。,成员对象与构造函数,2020/5/21,计算机基础教研室,88,【例4.6】含有成员对象的类的构造函数,classstudentIDlongvalue;public:studentID(longid=0)value=id;cout赋给学生的学号:valueendl;studentID()cout删除学号:valueendl;,2020/5/21,计算机基础教研室,89,classstudentprivate:studentIDid;charname20;public:student(charsname=noname,longsid=0):id(sid)strcpy(name,sname);cout“学生名:”nameendl;student()cout“删除学生名:nameendl;intmain()studentss(朱明,82020132);return0;,2020/5/21,计算机基础教研室,90,这样运行结果为:赋给学生的学号:82020132学生名:朱明删去学生名:朱明删去学号:82020132在student构造函数实现头部的冒号表示要对对象成员的构造函数进行调用。但在构造函数的声明中,冒号及冒号以后部分必须略去。,2020/5/21,计算机基础教研室,91,构造函数另一格式:对于不含对象成员的类对象的初始化,也可以套用以上的格式,把部分需要直接赋初值的变量初始化写在冒号的右边:类名:构造函数名(参数表):变量1(初值1),变量n(初值n)当然也可以把一部分变量重新放回花括号中的函数体。冒号以后部分实际是函数体的一部分,所以在构造函数的声明中,冒号及冒号以后部分必须略去。,成员对象与构造函数,2020/5/21,计算机基础教研室,92,构造函数和析构函数的调用规则:1.对全局定义的对象,当程序进入入口函数main之前对象就已经定义,整个程序结束时调用析构函数。2.对于局部定义的对象,每当程序控制流到达该对象定义处时,调用构造函数。当程序控制走出该局部域时,则调用析构函数。3.对于静态局部定义的对象,在程序控制首次到达该对象定义处时,调用构造函数。当整个程序结束时调用析构函数。,成员对象与构造函数,2020/5/21,计算机基础教研室,93,【例4.7】演示对象创建和撤消的对应关系,classcomplexprivate:doublereal,image;public:complex()/默认的构造函数real=0.0;image=0.0;coutInitializing00endl;complex(doubler,doublei=0.0)/带参数的构造函数real=r;image=i;coutInitializingrtiendl;complex(complex,2020/5/21,计算机基础教研室,94,voidassign(complexcom)real=com.real;/先建立临时对象comimage=com.image;voidprint()coutreal+imageiendl;inlinecomplex:complex(complex,2020/5/21,计算机基础教研室,95,complexglobal;/全局对象首先建立complexfun(complexcom)coutEnteringfunctionendl;global.assign(com);coutExitingfunctionendl;returnglobal;intmain()coutEnteringmainendl;complexcom1,com2(5.6,7.5);complexcom3=com1;com3.print();global.print();com1=fun(com2);com1.print();coutExitingmainendl;return0;,2020/5/21,计算机基础教研室,96,运行结果:Initializing00/全局对象global建立,调默认的构造函数Enteringmain/进入入口函数mainInitializing00/用默认的构造函数建立com1Initializing5.67.5/用带参数的构造函数建立com2Copy00/用复制的构造函数建立com30+0i/打印com30+0i/打印globalCopy5.67.5/调用全局函数fun(),调用复制构造函数建立/局部对象,fun()中的形参comEnteringfunction/进入全局函数fun()Copy5.67.5/进入global.assign(),调用复制构造函数/建立局部对象,assign()中的形参com,2020/5/21,计算机基础教研室,97,Destructor/退出global.assign(),调用析构函数,/清assign()中的形参comExitingfunction/将退出fun()Copy5.67.5/返回对象时调用复制构造函数建立临时对象Destructor/退出fun(),调用析构函数,清fun()的comDestructor/返回的临时对象赋给com1后析构5.6+7.5i/打印com1Exitmain/将退出入口函数mainDestructor/退出入口函数前,调用析构函数,清com3Destructor/退出入口函数前,调用析构函数,清com2Destructor/退出入口函数前,调用析构函数,清com1Destructor/退出入口函数前,调用析构函数,清global本例运行结果应与程序对比,看看程序运行的细节。,2020/5/21,计算机基础教研室,98,1只鸡1只鸭?,杨叔子院士谈“思考”:1只鸡1只鸭?本报讯(记者何辉实习生黄娟娟)“1只鸡1只鸭?”面对这个问题,可能很多人认为不同单位的物品不能相加,但中国科学院院士杨叔子教授这样回答:等于两只家禽。昨日,杨叔子来到武汉市52中,勉励数百名外来务工家庭子女要懂得思考和想象,不能拘泥于书本上的知识。“学习除了勤奋之外,还要会思考。有时在学习中看到特殊的、个性的东西,要善于转化成一般,要懂得从特殊个案看到一般现象,从具体事例看到抽象概念,这样的学习才能有创新。”杨叔子说,比如思维扩散了,甚至可以这样说:1只鸡1颗树2只生物。,2020/5/21,计算机基础教研室,99,运算符重载的概念:运算符的重载是特殊的函数重载,必须定义一个函数,并通知C+编译器,当遇到该重载的运算符时调用此函数。这个函数叫做运算符重载函数,通常为类的成员函数。运算符重载函数定义:返回值类型类名:operator重载的运算符(参数表)operator是关键字,它与重载的运算符一起构成函数名。因函数名的特殊性,C+编译器可以将这类函数识别出来。,运算符的重载,2020/5/21,计算机基础教研室,100,运算符重载是对已有的运算符赋予多重含义必要性C+中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)实现机制将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。编译系统对重载运算符的选择,遵循函数重载的选择原则。,运算符重载的实质,2020/5/21,计算机基础教研室,101,可以重载C+中除下列运算符外的所有运算符:.*:?:只能重载C+语言中已有的运算符,不可臆造新的。不改变原运算符的优先级和结合性。不能改变操作数个数。经重载的运算符,其操作数中至少应该有一个是自定义类型。,运算符重载的规则和限制,2020/5/21,计算机基础教研室,102,重载为类成员函数。重载为友元函数。,运算符重载的两种形式,重载为类成员函数时参数个数=原操作数个数-1(后置+、-除外)重载为友元函数时参数个数=原操作数个数,且至少应该有一个自定义类型的形参。,2020/5/21,计算机基础教研室,103,运算符函数是一种特殊的成员函数或友员函数成员函数的语法形式为:类型类名:operatorop(参数表)/相对于该类定义的操作,运算符要求的操作数,一个运算符被重载后,原有意义没有失去,只是定义了相对一特定类的一个新运算符,2020/5/21,计算机基础教研室,104,重载为成员函数,解释为:ObjectL.operatorop(ObjectR)左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递重载为友员函数,解释为:operatorop(ObjectL,ObjectR)左右操作数都由参数传递,二元运算符,ObjectLopObjectR,2020/5/21,计算机基础教研室,105,classComplexdoubleReal,Image;public:Complex(doubler=0.0,doublei=0.0):Real(r),Image(i)Complex(Complex,【例4.8】复数类,应用它进行复数运算,2020/5/21,计算机基础教研室,106,ComplexComplex:operator+(doubled)/重载+returnComplex(Real+d,Image);ComplexComplex:operator+=(Complexc)/重载+=Complextemp;/为了返回Complex类型的值,使+=可以连续使用temp.Real=Real+c.Real;temp.Image=Image+c.Image;Real=temp.Real;Image=temp.Image;returntemp;ComplexComplex:operator=(Complexc)/重载=Complextemp;/定义temp为可返回Complex类型值,使=可连续使用temp.Real=c.Real;temp.Image=c.Image;Real=temp.Real;Image=temp.Image;returntemp;doubleComplex:abs(void)/求绝对值函数returnsqrt(Real*Real+Image*Image);ComplexComplex:operator*(Complexc)/重载*returnComplex(Real*c.Real-Image*c.Image,Real*c.Image+c.Real*Image);,2020/5/21,计算机基础教研室,107,ComplexComplex:operator/(Complexc)/重载/doubled=c.Real*c.Real+c.Image*c.Image;returnComplex(Real*c.Real+Image*c.Image)/d,(Image*c.Real-Real*c.Image)/d);intmain(void)Complexc1(1.0,1.0),c2(2.0,2.0),c3(4.0,4.0),c;doubled=0.5;c1.Print();c=c2+c3;c.Print();c+=c1;c.Print();c=c+d;c.Print();/可用0.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论