C++程序设计课件:第4章 类与对象_第1页
C++程序设计课件:第4章 类与对象_第2页
C++程序设计课件:第4章 类与对象_第3页
C++程序设计课件:第4章 类与对象_第4页
C++程序设计课件:第4章 类与对象_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

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

文档简介

1、第4章 类与对象2022/9/20计算机基础教研室2类与对象 本章重点 C+中的类 对象的概念 构造函数 析构函数2022/9/20计算机基础教研室3回顾:面向过程的设计方法重点:如何实现细节过程,将数据与函数分开。形式:主模块+若干个子模块(main()+子函数)。模块是按功能来分的,所以也称功能块。在C+中称为一个函数,一个函数解决一个问题,即实现一个功能或一个操作。2022/9/20计算机基础教研室4回顾:面向过程的设计方法特点:自顶向下,逐步求精功能分解。缺点:效率低,程序的可重用性差。面向过程程序设计缺点的根源在于数据与数据处理分离。2022/9/20计算机基础教研室5面向对象的方法

2、使用面向对象的观点来描述模仿并处理现实问题。面向对象技术中的对象就是现实世界中某个具体的物理实体在计算机逻辑中的映射和体现。2022/9/20计算机基础教研室6对象类计算机世界实体类别现实世界客观世界抽象抽象实例化映射主观世界对象、实体与类现实世界中的实体可以抽象出类别的概念。对应于计算机世界就有一个类(class)的概念。面向对象就是计算机世界模拟现实世界。现实世界与计算机世界的映射关系2022/9/20计算机基础教研室7对象对 象面向对象编程的核心为计算机应用程序提供实用基础完成特定任务表示现实世界中的实体“对象是存在的具体实体,具有明确定义的状态和行为。”2022/9/20计算机基础教研

3、室8对象的示例收银员对象顾客对象顾客姓名:朱丽叶年龄:28体重:52千克操作:购买商品状态/特性姓名:布兰尼职衔:收银员年龄:35体重:60千克操作:收款打印帐单行为/操作“表示对象或实体拥有的特性称为属性”“对象执行的操作称为方法”2022/9/20计算机基础教研室9类类以共同特性和操作定义实体类是用于组合各个对象所共有操作和属性的一种机制形状类动物类汽车类类的示例“类是具有相同属性和行为的一组对象的集合”2022/9/20计算机基础教研室10类和对象的区别 类是概念模型, 定义对象的所 有特性和所需 的操作对象是真实的模型类和对象类定义实体对象是实际的实体类是对象的原型所有属于同一个类的对

4、象都具有相同的特性和操作2022/9/20计算机基础教研室11封装信息隐藏,隐藏对象的实现细节将东西包装在一起,然后以新的完整形式呈现出来例如,两种或多种化学药品组成一个胶囊将方法和属性一起包装到一个单元中,单元以类的形式实现“隐藏属性、方法或实现细节的过程称为封装。”2022/9/20计算机基础教研室12继承与派生是支持层次分类的一种机制,在保持原有类特性的基础上,进行更具体的说明。2022/9/20计算机基础教研室13多态性语文、数学、英语、政治、物理、化学、生物高中生计 算平均成绩大学生高数、英语、计算机、线性代数多态:同一名称,不同的功能实现方式。目的:达到行为标识统一,减少程序中标识

5、符的个数。2022/9/20计算机基础教研室14结构化程序与面向对象程序的比较问题:输入圆的半径,求圆的周长和面积数据描述:半径,周长,面积均用实型数表示数据处理:输入半径 r;计算周长 = 2*r ;计算面积 = * r2 ;输出半径,周长,面积; 2022/9/20计算机基础教研室15方法一:用结构化方法编程,求圆的周长和面积#includeusing namespace std;void main () double r, girth, area ; const double PI = 3.1415 ; cout r ; girth = 2 * PI * r ; area = PI *

6、r * r ; cout radius = r endl ; cout girth = girth endl ; cout area = area endl ;2022/9/20计算机基础教研室16方法二:用面向对象方法编程,求圆的周长和面积 实例化分析“圆”是抽象的类类型建立具体的圆(对象)半径?圆的周长 ? 面积 ?2022/9/20计算机基础教研室17方法二:用面向对象方法编程,求圆的周长和面积 圆类 属性 半径 方法 置半径值取半径值求周长 求面积实例化分析2022/9/20计算机基础教研室18方法二:用面向对象方法编程,求圆的周长和面积#includeusing namespace

7、std;class Circle double radius ;public : void Set_Radius( double r ) radius = r ; double Get_Radius() return radius ; double Get_Girth() return 2 * 3.14 * radius ; double Get_Area() return 3.14 * radius * radius ; ;void main() Circle A, B ; A.Set_Radius( 6.23 ) ; cout A.Radius = A.Get_Radius() endl

8、; cout A.Girth = A.Get_Girth() endl ; cout A.Area = A.Get_Area() endl ; B.Set_Radius( 10.5 ) ; cout B.radius = B.Get_Radius() endl ; cout B.Girth= B.Get_Girth() endl ; cout B.Area = B.Get_Area() endl ; 定义Circle类数据成员成员函数建立对象(类类型的变量)通过对象调用类的成员函数2022/9/20计算机基础教研室19类与对象的基本概念 4.1.3 对象的创建与使用 4.1.1 C+类的定义

9、4.1.2 成员函数的定义 20 类是一种数据类型。描述客观事物必须用不同的数据类型来描述不同的方面。 4.1.1 C+类的定义 class CGoodsprivate : char Name21;/商品名称 int Amount;/商品数量 float Price;/商品单价 float Total_value;/商品总价public : void RegisterGoods(char, int, float); /输入数据 void CountTotal( ); /计算商品总价值 void GetName(char); /读取商品名 int GetAmount( ); /读取商品数量 fl

10、oat GetPrice( ); /读取商品单价 float GetTotal_value( ); /读取商品总价值 ; class CGoods称为类头,关键字class是数据类型说明符,指出下面说明的是类;标识符CGoods是商品这个类的类型名最后的分号;不可少,表示是一条说明语句private和public是访问限定符花括号 中的部分称为类体,类体中定义了类成员表,包含数据成员和成员函数2022/9/20计算机基础教研室21访问限定符(access specifier):public(公共的)说明的成员能从外部进行访问。private(私有的)和protected(保护的)说明的成员不能

11、从外部进行访问。 每种说明符可在类体中使用多次。 访问限定符的作用域是从该说明符出现开始到下一个说明符之前或类体结束之前结束。 如果在类体起始点无访问说明符,系统默认定义为私有(private)。 访问限定符private(私有的)和protected(保护的)体现了类具有封装性。4.1.1 C+类的定义 2022/9/20计算机基础教研室22封装: 类把数据(事物的属性)和函数(事物的行为操作)封装为一个整体。 接口: 通常数据成员被说明成私有的,函数成员被说明成公有的;从外部对数据成员进行操作,只能通过公有函数来完成,数据受到了良好的保护,不易受副作用的影响。公有函数集定义了类的接口(in

12、terface)。 成员函数可以直接使用类定义中的任一成员,可以处理数据成员,也可调用函数成员。注意: 类是一种数据类型,定义时系统不为类分配存储空间,所以不能对类的数据成员初始化。类中的任何数据成员也不能使用关键字extern、auto或register限定其存储类型。 2022/9/20计算机基础教研室234.1.2 成员函数的定义 通常在类定义中,成员函数仅作声明。函数定义通常在类的说明之后进行,其格式如下:返回值类型 类名:函数名(参数表) /函数体 运算符“:”称为作用域解析运算符(scope resolution operator),它指出该函数是属于其左操作数对应的类的成员函数。

13、24类CGoods成员函数的定义void CGoods:RegisterGoods(char name , int amount , float price) strcpy(Name , name) ; /字符串复制函数 Amount = amount ; Price = price ;void CGoods:CountTotal(void) Total_value = Price*Amount;void CGoods:GetName(char name) strcpy(name , Name);int CGoods:GetAmount(void) return(Amount) ;float

14、CGoods:GetPrice(void) return(Price) ;float CGoods:GetTotal_value(void) return(Total_value) ;2022/9/20计算机基础教研室25定义对象: 对象是类的实例(instance)。定义一种数据类型只是告诉编译系统该数据类型的构造,并没有预定内存。类只是一个样板,以此样板可以在内存中开辟出同样结构的实例对象。格式如下:CGoods Car; 这个定义创建了CGoods类的一个对象Car,同时为它分配了属于它自己的存储块,用来存放数据和对这些数据实施操作的成员函数(代码)。对象只在定义它的域中有效。4.1.3

15、 对象的创建与使用 2022/9/20计算机基础教研室26数据区对象1数据区对象数据区对象公共代码区 系统为每个对象分配一个数据区,公共代码区(放成员函数的区域)为各对象共用。 注意: 区别同一个类的各个不同对象是由数据成员决定的;操作的代码对所有对象都是一样的。 通过sizeof计算对象占用的存储空间时不包括函数代码所占用的存储空间。 对象的存储2022/9/20计算机基础教研室27#includeusing namespace std;class Circle double radius ;public : void Set_Radius( double r ) ; double Get_

16、Radius() ; double Get_Girth() ; double Get_Area() ; ;Circle 类定义数据成员声明成员函数声明回顾 用面向对象方法编程,求圆的周长和面积 2022/9/20计算机基础教研室28void Circle:Set_Radius(double r) radius = r; double Circle:Get_Radius() return radius; double Circle:Get_Girth() return 2 * 3.14f * radius; double Circle:Get_Area() return 3.14f * radi

17、us * radius; 回顾 用面向对象方法编程,求圆的周长和面积 成员函数实现2022/9/20计算机基础教研室29void main() Circle A, B; A.Set_Radius(6.23) ; coutA.Radius = A.Get_Radius()endl ; coutA.Girth = A.Get_Girth()endl ; cout A.Area = A.Get_Area()endl ; B.Set_Radius( 10.5 ) ; coutB.radius = B.Get_Radius()endl ; coutB.Girth=B.Get_Girth()endl ;

18、coutB.Area = B.Get_Area()endl ; 建立对象(类类型变量)通过对象调用类的成员函数回顾 用面向对象方法编程,求圆的周长和面积 2022/9/20计算机基础教研室30内联函数: 在类定义外部定义的成员函数之前可以使用inline关键字说明其为内联函数;在类定义中定义的成员函数则可以省略inline,系统将自动是其为内联函数。 如Get_Area()函数可定义为:inline double Circle:Get_Area() return 3.14f * radius * radius; 注意:inline只是一个建议,最后由编译器决定是否执行。对象的存储方式是物理的,

19、这是由计算机来完成的,它并不影响类在逻辑上的封装性。2022/9/20计算机基础教研室31数据成员多为私有的,要对它们进行初始化,必须用一个公有函数来进行。同时这个函数应该在且仅在定义对象时自动执行一次。称为:构造函数(constructor)4.3.1构造函数的定义与使用 4.3.2析构函数的定义与使用4.3 构造函数与析构函数 2022/9/20计算机基础教研室32由于类的封装性,类的对象不能象普通变量一样初始化。构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。在对象创建时由系统自动调用。如果程序中未声明,则系统自动产生出一个默认形式的构造函数。构造

20、函数允许为内联函数、重载函数、带默认参数值的函数。4.3.1 构造函数的定义与使用2022/9/20计算机基础教研室33函数名与类名相同。构造函数无函数返回类型说明。注意是什么也不写,也不可写void。构造函数可以在类中定义,也可以在类外定义。构造函数可以重载,系统在自动调用时按一般函数重载的规则选一个执行。构造函数的特征CGoods:CGoods() Name0 = 0; Price = 0; Account = 0; Total_value = 0;CGoods:CGoods(char name) strcpy(Name, name); Price = 0; Account = 0; To

21、tal_value = 0; 2022/9/20计算机基础教研室34如果类定义中没有给出构造函数,则编译器自动给出一个默认的构造函数: 类名( ) 但只要定义了一个构造函数,系统就不会自动生成默认的构造函数。如果定义的构造函数是无参的或各参数均有默认值的,编译器会认为其是默认的构造函数,默认的构造函数只能有一个 。建立新对象时,该对象所属的类的构造函数自动被调用,并且在其生命期中只调用一次。构造函数的特征2022/9/2035#include using namespace std;class Q int x, y;public: Q(int a, int b) cout构造函数Q(a, b)

22、endl; x=a; y=b; Q(int a) cout构造函数Q(a)endl; x=a; y=0; void P(void) coutxtyendl; ;void main(void) Q q1(50,100); q1.P(); Q q2(50); q2.P();输出:构造函数Q(a,b)50100构造函数Q(a)500构造函数举例 2022/9/20计算机基础教研室36析构函数特征: 当一个对象的生命周期结束时,C+会自动调用析构函数对该对象并进行善后工作。1.构函数名与类名相同,但在前面加上字符 ,如:CGoods()2.析构函数无函数返回类型,与构造函数在这方面是一样的,但析构函数

23、不带任何参数。3. 一个类只能有一个析构函数,这与构造函数不同。类定义中没有给出析构函数时,编译器也自动给出一个默认的析构函数。4. 对象注销时,系统自动调用析构函数。4.3.2 析构函数的定义与使用2022/9/2037#include using namespace std;class Q int x, y;public: Q(int a, int b) cout构造函数Q(a, b)endl; x=a; y=b; Q() cout析构函数Q()endl; void P(void) coutxtyendl; ;void main(void) Q q1(50,100); q1.P(); co

24、ut退出主函数!n;输出:构造函数Q(a,b)50100退出主函数!析构函数Q()析构函数举例 2022/9/20计算机基础教研室38一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。游泳池过道类的应用举例2022/9/20计算机基础教研室39#include using namespace std;const float PI = 3.14159;const float FencePrice = 35;const float ConcretePrice

25、 = 20;/声明类Circle及其数据和方法class Circle private: float radius; public: Circle(float r); /构造函数 float Circumference(); /圆周长 float Area() ; /圆面积;Circle:Circle(float r) /构造函数初始化数据成员radius radius = r; float Circle:Circumference() /计算圆的周长 return 2 * PI * radius; float Circle:Area() /计算圆的面积 return PI * radius

26、* radius;2022/9/20计算机基础教研室40void main() float radius; float FenceCost, ConcreteCost; /提示用户输入半径 coutradius; /声明 Circle 对象 Circle Pool(radius); Circle PoolRim(radius + 3); /计算栅栏造价并输出 FenceCost = PoolRim.Circumference() * FencePrice; coutFencing Cost is ¥FenceCostendl; /计算过道造价并输出 ConcreteCost = (PoolRi

27、m.Area() - Pool.Area()*ConcretePrice; coutConcrete Cost is ¥ConcreteCostendl;运行结果:Enter the radius of the pool: 10Fencing Cost is ¥2858.85Concrete Cost is ¥4335.392022/9/20计算机基础教研室414.4.1 引用 4.4.2 复制构造函数 4.4.3 成员对象与构造函数 4.4 引用与复制构造函数2022/9/20计算机基础教研室42引用的导入: 传值方式的参数传递是在函数域中为形参分配内存,而把实参的数值传递到新分配的内存中。

28、它的优点是实现实参与形参隔离,有效避免函数的副作用。 问题:如果要求改变实参的值,怎么办?如果实参是一个复杂的对象,重新分配内存会引起程序执行效率大大下降,怎么办? 有一种导出型数据类型引用(reference)可以解决上面的难题。引用又称别名(alias)。引用2022/9/20计算机基础教研室43引用&在这里是引用的说明符 引用是给一个已经定义的变量重新起一个别名,而不是定义一个新的变量,定义的格式为:类型 &引用类型变量名 = 已定义过的变量名;例如:double number;double &newnum = number;注意: newnum是变量number的别名,C+系统不为引用

29、类型变量分配内存空间 。 在程序中修改了newnum也就是修改了number,两位一体。 引用主要用于函数之间的数据传递。44【例4.3】引用作为形参 Xyd1d2temp1.4142.7181.4142.7181.414参数d1、d2为引用时内存分配示意 void swap(double & d1, double & d2) double temp ; temp=d1 ; d1=d2 ; d2=temp ; int main(void) double x , y ; cout请输入x和y的值 xy ; swap(x,y) ; coutx=xt y=yn; return 0; 45 同一个类的

30、对象在内存中有完全相同的结构,如果作为一个整体进行复制是完全可行的。这个复制过程只需要复制数据成员,而成员函数是共用的。 在建立对象时可用同一类的另一个对象来初始化该对象,这时所用的构造函数称为复制构造函数。复制构造函数复制构造函数的特征:1. 复制构造函数的参数必须采用引用。2.系统会自动提供称为默认的按成员语义支持的复制构造函数,亦称为默认的按成员初始化。按成员作复制是通过依次复制每个数据成员实现的。3.同类对象之间可以用赋值运算符 = 直接复制。2022/9/20计算机基础教研室46CGoods:CGoods(CGoods &cgd) strcpy(Name, cgd.Name); Pr

31、ice = cgd.Price; Amount = cgd.Amount; Total_value = cgd.Total_valueCGood Car1(夏利2000,30,98000.00);/调用三个参数的构造函数CGood Car2 = Car1; /调用复制构造函数CGood Car3 (Car1); /调用复制构造函数,Car1为实参这样三个对象的初始化结果完全一样。复制构造函数 当成员函数的参数为同一类(class)的对象或它的引用,在函数体内使用参数对象的私有数据成员时,可用对象名加成员访问操作符点号进行。 从逻辑上讲,每个对象有自己的成员函数,访问同类其他对象的私有数据成员应

32、通过该对象的公有函数,不能直接访问。但在物理上只有一个成员函数代码,所以直接访问是合理的。仅在成员函数中可以这样做。2022/9/20计算机基础教研室47class Pointpublic: Point(int xx=0, int yy=0)X=xx; Y=yy; Point(Point& p); int GetX() return X; int GetY() return Y;private: int X, Y;Point:Point (Point &p) X = p.X; Y = p.Y; cout复制构造函数被调用endl;复制构造函数举例2022/9/20计算机基础教研室48(1)当用

33、类的一个对象去初始化该类的另一个对象时系统自动调用复制构造函数实现拷贝赋值。void main(void) Point A(1, 2); Point B(A); /复制构造函数被调用 coutB.GetX()endl;复制构造函数调用的三种情况2022/9/20计算机基础教研室49(2)若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用复制构造函数。 void fun1(Point p) coutp.GetX()endl; void main() Point A(1, 2); fun1(A); /调用复制构造函数 复制构造函数调用的三种情况2022/9/20计算机基础教研室50(3

34、)当函数的返回值是类对象时,系统自动调用复制构造函数。Point fun2() Point A(1, 2); return A; /调用复制构造函数void main() Point B; B = fun2(); 复制构造函数调用的三种情况2022/9/20计算机基础教研室51聚合(aggregation): 类中的成员,除了数据成员和成员函数外,还有成员对象,即用其他类的对象作为类的成员。使用成员对象的技术称为聚合。成员对象是实体,系统不仅为它分配内存,而且要进行初始化。成员对象与构造函数2022/9/20计算机基础教研室52定义形式:类名:类名(参数表) : 对象1(参数), 对象2(参数

35、), . 本类初始化 其中,参数表可以包含成员对象和数据成员初始化所需的形参。 冒号以后部分称为初始化区,是函数体的一部分,在构造函数的声明中不应被包含。 初始化区主要用于完成成员对象的初始化,也可以在该处对数据成员进行初始化。含成员对象的构造函数2022/9/20计算机基础教研室53class Pointprivate: float x,y; /点的坐标public: Point(float xx, float yy); /构造函数 float GetX(void) return x; /取X坐标 float GetY(void) return y;/取Y坐标;类聚合构造函数实例class

36、Lineprivate: Point p1, p2; /线段的两个端点 double s; /线段的长度public: Line(Point a, Point b); /构造函数声明,无初始化区;2022/9/20计算机基础教研室54Line:Line(Point a, Point b):p1(a), p2(b) double x = double(p1.GetX() - p2.GetX(); double y = double(p1.GetY() - p2.GetY(); s = sqrt(x*x+y*y); 类聚合构造函数实例Line:Line(Point a, Point b):p1(a

37、), p2(b), s(0)2022/9/20计算机基础教研室55 含对象成员的析构函数: 因为析构函数没有参数,所以包含成员对象的类的析构函数形式上并无特殊之处。但是撤销该类对象时,会首先调用自己的析构函数,再调用成员对象的析构函数,调用次序与初始化时的次序相反。成员对象与构造函数2022/9/20计算机基础教研室56【例4.6】含有成员对象的类的构造函数#include using namespace std;class StudentID long value;public: StudentID(long id=0) value=id; cout赋给学生的学号:valueendl; St

38、udentID() cout删除学号:valueendl; ;2022/9/20计算机基础教研室57class Studentprivate: StudentID id; char name20;public: Student (char sname=no name, long sid=0):id(sid) strcpy(name, sname); cout学生名:nameendl; Student() cout删除学生名:nameendl; ;int main() Student ss(朱明, 82020132); return 0;运行结果为:赋给学生的学号: 82020132学生名:朱明

39、删除学生名:朱明删除学号: 820201322022/9/20计算机基础教研室58构造函数和析构函数的调用顺序:1. 对全局定义的对象,当程序进入入口函数main之前对象就已经定义,整个程序结束时调用析构函数。2. 对于局部定义的对象,每当程序控制流到达该对象定义处时,调用构造函数。当程序控制走出该局部域时,则调用析构函数。3. 对于静态局部定义的对象,在程序控制首次到达该对象定义处时,调用构造函数。当整个程序结束时调用析构函数。成员对象与构造函数2022/9/20计算机基础教研室59【例4.7】演示对象创建和撤消的对应关系#include using namespace std;class

40、complexprivate: double real, image; public: complex() /默认的构造函数 real=0.0;image=0.0; coutInitializing 0 0endl; complex(double r,double i=0.0) /带参数的构造函数 real=r;image=i; coutInitializingrtiendl; complex(complex &com); /复制的构造函数声明 complex()cout Destructorendl; void assign(complex com) real=com.real; image

41、=com.image; void print() coutreal+imageiendl; ;2022/9/20计算机基础教研室60inline complex:complex(complex &com)/复制构造函数的定义 coutCopycom.realtcom.imageendl; real=com.real; image=com.image;complex global; /全局对象首先建立complex fun(complex com) coutEntering functionendl; global.assign(com); coutExiting functionendl; r

42、eturn global; int main() cout Entering main endl; complex com1, com2(5.6, 7.5); complex com3 = com1; com3.print(); global.print(); com1=fun(com2); com1.print(); coutExiting mainendl; return 0;2022/9/20计算机基础教研室61运行结果:Initializing 0 0 /全局对象global建立,调默认的构造函数Entering main /进入入口函数mainInitializing 0 0 /用默

43、认的构造函数建立com1Initializing 5.6 7.5 /用带参数的构造函数建立com2Copy 0 0 /用复制的构造函数建立com30+0i /打印com30+0i /打印globalCopy 5.6 7.5 /调用全局函数fun(),调用复制构造函数建立 /局部对象,fun()中的形参comEntering function /进入全局函数fun()Copy 5.6 7.5 /进入global.assign(),调用复制构造函数 /建立局部对象,assign()中的形参com2022/9/20计算机基础教研室62Destructor /退出global.assign(),调用析

44、构函数, /清assign()中的形参comExiting function /将退出fun()Copy 5.6 7.5 /返回对象时调用复制构造函数建立临时对象Destructor /退出fun(),调用析构函数,清fun()的comDestructor /返回的临时对象赋给com1后析构5.6 + 7.5i /打印com1Exit main /将退出入口函数mainDestructor/退出入口函数前,调用析构函数,清com3Destructor/退出入口函数前,调用析构函数,清com2Destructor/退出入口函数前,调用析构函数,清com1Destructor/退出入口函数前,调用

45、析构函数,清global本例运行结果应与程序对比,看看程序运行的细节。2022/9/20计算机基础教研室63运算符重载的概念:运算符的重载是特殊的函数重载,必须定义一个函数,并通知C+编译器,当遇到该重载的运算符时调用此函数。这个函数叫做运算符重载函数,通常为类的成员函数。 一个运算符被重载后,原有意义没有失去,只是定义了相对某个特定类的一个新运算符。 4.5 运算符的重载2022/9/20计算机基础教研室64可以重载C+中除下列运算符外的所有运算符:. .* : ?:只能重载C+语言中已有的运算符,不可臆造新的。不改变原运算符的优先级和结合性。不能改变操作数个数。经重载的运算符,其操作数中至

46、少应该有一个是自定义类型。运算符重载的规则和限制2022/9/20计算机基础教研室65重载为成员函数,解释为:ObjectL.operator+ (ObjectR) 左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递 ObjectL + ObjectR 二元运算符+ 语法形式为:类型 类名 : operator op(参数表) /相对于该类定义的操作 operator是关键字,它与重载的运算符op一起构成函数名。2022/9/20计算机基础教研室66class Complex double Real, Image ;public: Complex(double r=

47、0.0, double i=0.0):Real(r),Image(i) Complex(Complex &com)Real=com.Real; Image=com.Image; void Print() coutReal=RealtImage=Imagen; Complex operator+(Complex); /重载+运算符函数 Complex operator+(double); /重载+运算符函数 Complex operator=(Complex); /重载=运算符函数; Complex Complex:operator+(Complex c)/重载+ Complex Temp(Re

48、al+c.Real , Image+c.Image) ; return Temp; 【例4.8】复数类,应用它进行复数运算2022/9/20计算机基础教研室67Complex Complex:operator+(double d) /重载+ return Complex(Real+d , Image); Complex Complex:operator=(Complex c)/重载= Complex temp; /定义temp为可返回Complex类型值,使=可连续使用 temp.Real=c.Real; temp.Image=c.Image; Real=temp.Real; Image=te

49、mp.Image; return temp;int main(void) Complex c1(1.0,1.0), c2(2.0,2.0), c3(4.0,4.0), c; double d=0.5; c1.Print(); c=c2+c3; c.Print(); c=c+d; c.Print(); /可用0.5代替d c=c3=c2=c1; c.Print(); /连续赋值 return 0; 在return后面跟的表达式中调用的是类的构造函数,它为新建的作为返回值载体的无名对象进行初始化。 2022/9/20计算机基础教研室68运算符的重载引用作为参数: Complex Complex:o

50、perator+(const Complex &c) return Complex(real+c.real, Image+c.Image) ; 注意:参数采用对象的引用而不是对象本身,调用时不再重新分配内存建立一个复制的对象,函数效率会更高。而在引用形式参数类型说明前加const关键字,表示被引用的实参是不可改变的,如程序员不当心在函数体中重新赋值了被引用的实参, C+编译器会认为出错。2022/9/20计算机基础教研室692.当用类的成员函数实现运算符的重载时,运算符重载函数的参数(当为双目运算符时)为一个或(当为单目运算符时)没有。运算符的左操作数一定是对象,因为重载的运算符是该对象的成员

51、函数,而右操作数是该函数的参数。 3.单目运算符“+”和“-”存在前置与后置问题。前置“+”格式为: 返回类型 类名:operator+() 而后置“+”格式为: 返回类型 类名:operator+(int) 后置“+”中的参数int仅用作区分。小结:1. 运算符重载函数的函数名必须为关键字operator加一个合法的运算符。C+中只有极少数的运算符不允许重载。 运算符的重载2022/9/20计算机基础教研室70运算符的重载问题:例5.7中:c = c + d;语句,改为c = d + c;因为d不是Complex的对象,C+编译器将无法找到合适的重载的“+”运算符对应的函数,最终给出出错信息

52、。怎样解决? 2022/9/20计算机基础教研室71通过声明为模块B的友元,模块A能够直接引用到模块B中被隐藏的信息。友元破坏了数据封装和数据隐藏的机制,应尽量不使用或少使用友元。可以使用友元函数和友元类。友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名直接访问private和protected成员。4.6 友元2022/9/20计算机基础教研室72 重载为友员函数,解释为:operator+ (ObjectL, ObjectR) 左右操作数都由参数传递 二元运算符ObjectL + ObjectR2022/9/20计算机基础教研室73class Co

53、mplex friend Complex operator + (double,Complex); /opration+说明为类Complex类的友元函数Complex operator + (double d , Complex c) return Complex(d + c.Real , c.Image) ; /friend只用于类说明中,定义时不加friend/注意友元不是成员函数,但可以直接访问私有成员int main(void) ; c=d+c1; c.print(); return 0;解释:d+c1被C+编译器解释为:operator+(d, c1)友元 2022/9/20计算机

54、基础教研室74例4.8_1】 用友元函数重载运算符class Complex doubleReal, Image ;public : Complex(double r=0.0, double i=0.0) : Real(r), Image(i) Complex(Complex &com) Real = com.Real; Image=com.Image; void Print() coutReal=RealtImage=Imagen friend Complex operator+(const Complex &,const Complex &); friend Complex &operat

55、or +=(Complex &,const Complex &); ;2022/9/20计算机基础教研室75Complex &operator +=(Complex &c1,const Complex &c2) /重载复数+= c1.Real = c1.Real + c2.Real; c1.Image = c1.Image + c2.Image; return c1; /返回由引用参数传递过来的变量,函数返回值可为引用Complex operator+(const Complex &c1,const Complex &c2) return Complex(c1.Real + c2.Real,

56、c1.Image + c2.Image); /隐式说明局部对象int main(void) Complex c1(1.0,1.0) , c2(2.0,2.0) , c3(4.0,4.0) , c; double d=0.5 ; c1.Print(); c=c2+c3; c.Print(); /两复数相加 c+=c2+=c1; c.Print(); /连续加赋值 c=c+d; c.Print(); /复数加实数 c=d+c; c.Print(); /实数加复数 return 0;2022/9/20计算机基础教研室76友元函数注意点: 1.友元函数不是类的成员函数,在函数体中访问对象的成员,必须用

57、对象名加运算符.加对象成员名。 2.友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,结果一样。 3.某类的友元函数的作用域并非该类域。如果该友元函数是另一类的成员函数,则其作用域为另一类的类域,否则与一般函数相同。友元类:整个类可以是另一个类的友元。友元类的每个成员函数都是另一个类的友元函数,都可访问另一个类中的保护或私有数据成员。定义方法如下:class A friend class B; /声明B为A的友元类 ;2022/9/20计算机基础教研室77一个类的所有对象具有相同的属性;描述类的所有对象的共同特征的一个数据项,对于任何对象实例,它的属性值是相同的。4.7 静态成员2022/9/20计算机基础教研室784.7 静态成员 在类定义中,用关键字static修饰的数成员为静态成员。包括静态数据成员和静态成员函数。 类的所有对象共享由系统为静态数据成员分配的一个存储空间,而这个存储空间是在编译时分配的,在定义对象时不再为静态数据成员分配空间。 静态数据成员

温馨提示

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

评论

0/150

提交评论