《C语言程序设计第五章类和对象.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计第五章类和对象.ppt(81页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第五章 类和对象(一)第一节 类的定义第五章 一、一、类的定义:类的定义:类:类:是一种复杂的数据类型,它是将不同类型的是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。数据和与这些数据相关的操作封装在一起的集合体。因此,类具有更高的抽象性抽象性,类中的数据具有隐藏数据具有隐藏性性,类还具有封装性。具有封装性。二、二、类的定义格式:类的定义格式:类的定义格式包括:说明部分和实现部分。说明部分和实现部分。说明部分:说明部分:说明该类中的成员。实现部分:实现部分:对成员函数的定义。成员:成员:包含数据成员和成员函数。包含数据成员和成员函数。成员函数:成员函数:是用
2、来对数据成员进行操作的是用来对数据成员进行操作的,又称为 “方法”。第五章 概括起来说,说明部分将告诉使用者“干什么”,而实现部分是告诉使用者“怎么干”。因此,使用者关心的往往是说明部分,而实现部分是一些不必关心的信息。类的一般定义格式类的一般定义格式:class class public public:private:private:;第五章说明:说明:1、类的成员包含成员函数和数据成员两部分。从访问 权限上来分,类的成员分为类的成员分为:公有的公有的(public)、私有、私有的的 (private)和保护的和保护的(protected)三类。三类。、关键字关键字public,privat
3、e 和和 protected 被称为访问被称为访问 权限修饰符或访问控制修饰符,用它们来说明类成权限修饰符或访问控制修饰符,用它们来说明类成 员的访问权限。员的访问权限。它们在类体内出现的先后顺序无关,并且允许多次出现。、公有部分往往是一些操作公有部分往往是一些操作(即成员函数即成员函数)。它为用户 提供接口功能,公有成员可以在程序中引用。、私有部分通常是一些数据成员。私有部分通常是一些数据成员。这些成员是用来 描述该类中的对象的属性的,是被用来隐藏隐藏的部分第五章 用户无法访问它们,只有成员函数或经特殊说明的只有成员函数或经特殊说明的 函数才可以引用数据成员。函数才可以引用数据成员。2 2、
4、是类定义中的实现部分,这这 部分包含所有在类体内说明的函数的定义部分包含所有在类体内说明的函数的定义。如果一 个成员函数在类体内定义了,实现部分将不出现。如 果所有的成员函数都在类体内定义,则实现部分可以 省略。如果成员函数定义在类体外,则须在成员函数 头的前面要加上该函数所属类的标识,这时使用作 用域运算符 。作用域运算符的使用格式如下:函数类型函数类型 ()第五章例例1 1、定义一个关于日期的类。class Tdate public:void SetDate(int y,int m,int d);int ISLeap Year();void Print();private:int year
5、,month,day;;void TDate SetDate(int y,int m,int d)year=y;month=m;第五章 day=d;int TDate ISLeapYear()return(year%4=0&year%100!=0)|(year%400=0);void TDate Print()coutyear.month.dayendl;如果例中将成员函数的实现部分(即函数定义)都写在了类体内,那么类的实现部分就可省略了。因此关于日期类的定义还可以写成如下程序:第五章class TDatepublic:void SetDate(int y,int m,int d)year=y
6、;month=m;day=d;int IsLeapYear()return(year%4=0&year%100!=0)|(year%400=0);void Print()coutyear.month.dayendl;private:int year,month,day;;第五章例例2 2、定义一个点类class TPoint public:void SetPoint(int x,int y);int Xcoord()return X;int Ycoord()return Y;void Move(int xOffset,intyOffset);private:int X,Y;void TPoin
7、t SetPoint(int x,int y)X=x;Y=y;第五章 void TPoint:Move(int xOffset,int yOffset)X+=xOffset;Y+=yOffset;三、三、定义类时应注意的事项:定义类时应注意的事项:1、在类体中不允许对所定义的数据成员进行初始化。在类体中不允许对所定义的数据成员进行初始化。如前面在日期类的定义中这样编写程序:第五章class TDate public:private:int year(1998),month(4),day(9);;这里,对数据成员year,month 和 day 进行初始化是错误的。2、类中的数据成员的类型可以是
8、任意的类中的数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是对可以是对 象。另一个类的对象,可以作该类的成员,但是自象。另一个类的对象,可以作该类的成员,但是自 身类的对象是不可以的,当另一个类的对象作为这身类的对象是不可以的,当另一个类的对象作为这第五章个个类的成员时类的成员时,如果另一个类的定义在后,需要提前说如果另一个类的定义在后,需要提前说明。明。如:class N;/说明类 Nclass M public:private:N n;/n是N类的对象;class N public:void f(M m);/m是M类的对象;第五章3、尽管在类体内公有成员与
9、私有成员的说明顺序无 关,但是一般地,类体内先说明公有成员一般地,类体内先说明公有成员,再再说明说明 私有成员,在说明数据成员时私有成员,在说明数据成员时,一般按数据成员的类一般按数据成员的类 型型大小大小,由小至大说明由小至大说明。4、在编程时经常习惯地将类定义的说明部分或者整个 定义部分(包含实现部分)放到一个头文件中,使得 后面引用起来比较方便。上面定义的日期类和点类 的例子,可放在.h扩展名的文件中,即 Tdate.h和 Tpoint.h文件。第二节 对象的定义第五章 根据类的定义,类是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。由于由于类中的成类中的成员函数是共享的,因
10、此由同一个类所创建的对象的数员函数是共享的,因此由同一个类所创建的对象的数据结构是相同的。两个不同的对象的名字是不同的,据结构是相同的。两个不同的对象的名字是不同的,它们的数据结构的内容(即数据成员的值)是不同的。它们的数据结构的内容(即数据成员的值)是不同的。所以,系统对已定义的对象仅给它分配数据成员变量,而一般数据成员又都为私有成员,不同对象的数据成员的值可以是不相同的。第五章一、一、对象的定义格式:对象的定义格式:1 1、对象的定义格式:、对象的定义格式:(1)、一般对象的定义格式 类名对象名表;类名对象名表;(2)、指向对象的指针定义格式 类名类名*指针名;指针名;(3)、对象引用的定
11、义格式 类名类名&引用名引用名=对象名;对象名;2 2、对象成员的表示方法:、对象成员的表示方法:(1)、一般对象的成员表示方法:、.、.()第五章 用来表示数据成员,用来表示成员函数的。“”是一个运算符是一个运算符,功能是表示对象的成员。功能是表示对象的成员。(2)、指向对象的指针的成员表示方法:、-、-()“-”“-”也也是一个表示成员的运算符是一个表示成员的运算符,是用来表是用来表示指向对象的指针的成员。示指向对象的指针的成员。-等价于 (*).-()等价于 (*).()第五章例例3 3、分析下列程序的输出结果。#include#include tdate.hvoid main()TDa
12、te date1,date2;date1.SetDate(1996,5,4);date2.SetDate(1998,4,9);int leap=date1.IsLeapYear();coutleapendl;date1.Print();date2.Print();为了阅读方便,我们把前面的tdate.h程序写在下面:第五章class TDate public:void SetDate(int y,int m,int d)year=y;month=m;day=d;int IsLeapYear()return (year%4=0&year%100!=0)|(year%400=0);void Pri
13、nt()coutyear.month.dayendl;private:int year,month,day;执行该程序后,输出结果如下:1 第五章 程序分析:该程序的主函数中,定义了两个对象date1和date2,并通过成员函SetDate()给对象 date1 和 date2 赋值。通过成员函数 IsLeapYear()判断对象 date1 的年份(1996)是否是闰年。最后,通过调用成员函数Print()输出显示对象date1 和 date2 的数据成员的值。例4.分析下列程序的输出结果。#include#includetpoint.hvoid main()TPoint p1,p2;第五章
14、 p1.SetPoint(3,5);p2.SetPoint(8,10);p1.Move(2,1);p2.Move(1,-2);coutx1=p1.Xcoord(),y1=p1.Ycoord()endl;coutx2=p2.Xcoord(),y2=p2.Ycoord()endl;同样为了分析的方便,把建立的点类头文件写在下面。class TPoint public:void SetPoint(int x,int y);int Xcoord()return X;第五章 int Ycoord()return Y;void Move(int xOffset,int yOffset);private:i
15、nt X,Y;void TPointSetPoint(int x,int y)X=x;Y=y;void TPointMove(int xOffset,int yOffset)X+=xOffset;Y+=yOffset;第五章 运行该程序,输出结果为:x1=5,y1=6 x2=9,y2=8 程序分析:在主程序中,先定义Tpoint类的两个对象p1,p2;调用成员函数SetPoint()分别为p1,p2对象的数据成员赋值;再调用Move()成员函数为p1,p2的数据成员分别重新赋值;调用Xcoord()和Ycoord()两个成员函数通过为p1赋值而分别输出x1,y1值,同样原理输出x2,y2值。第
16、三节 对象的初始化第五章一、一、构造函数和析构函数:构造函数和析构函数:1.1.构造函数:构造函数:、构造函数的功能:构造函数的功能:在创建对象时在创建对象时,系统自动调用相应的构造函数为系统自动调用相应的构造函数为 对象初始化。对象初始化。、构造函数的特点构造函数的特点:a、构造函数是成员函数是成员函数,函数体可写在类体内,也可 写在类体外。b、构造函数是一个函数名与类名相同的特殊函数是一个函数名与类名相同的特殊函数,定 义时无类型说明无类型说明。c、构造函数可以有一个参数,也可以有多个参数,还 可以无参数,并可以重载。可以重载。第五章d、程序中不能直接调用构造函数,在创建对象时系统在创建对
17、象时系统 自动调用。自动调用。e、当一个类中没有定义任何构造函数时,系统将自动没有定义任何构造函数时,系统将自动 创建一个默认构造函数。创建一个默认构造函数。2、析构函数:析构函数:、析构、析构函数的功能:函数的功能:是用来释放一个对象的,与构造函数的功能正好是用来释放一个对象的,与构造函数的功能正好 相反。相反。在对象删除前,用它来做一些清理工作。、析构函数的特点析构函数的特点:a、析构函数是成员函数是成员函数,函数体可写在类体内,也可 以写在类体外。b、析构函数也是一个特殊的函数,它的函数名也同函数名也同第五章 类名类名,定义时也无类型说明也无类型说明,但为了与构造函数加以 区别,在函数名
18、函数名前面要加前面要加“”字符字符。c、析构函数无参数,无参数,因此无法重载无法重载。一个类中只可能 定义一个析构函数。d、当一个系统没有定义析构函数时没有定义析构函数时,系统将自动创建自动创建 一个默认的析构函数。一个默认的析构函数。e、析构函数可以被调用,也可以被系统自动调用。在 下面两种情况下,析构函数会被自动调用:、如果一个对象被定义在一个函数体内,则当这个 函数结束时,该对象的析构函数被自动调用。、当一个对象是使用new 运算符被动态创建的,在 使用 delete 运算符释放它时,delete将会自动第五章 调用析构函数。例5、利用构造函数与析构函数重新定义前面讲过的日 期类,并将其
19、定义存放在tdate1.h 文件中。分析程 序的运行结果。class TDate1 public:TDate1(int y,int m,int d);TDate1();void Print();private:int year,month,day;;TDate1TDate1(int y,int m,int d)第五章 year=y;month=m;day=d;coutConstructor called.n;TDate1TDate1()coutDestructor called.n;void TDate1Print()coutyear.month.dayendl;#include#includ
20、e tdate1.hvoid main()第五章 TDatel today(1998,4,9),tomorrow(1998,4,10);couttoday is;today.Print();couttomorrow is;tomorrow.Print();执行该程序后,输出结果应为:Constructor Called.Constructor Called.tomorrow is 1998.4.10 Destructor called.Destructor called.第五章二、默认二、默认构造函数和默认析构函数:构造函数和默认析构函数:在类定义时没有定义任何构造函数时在类定义时没有定义任何
21、构造函数时,则编译器自则编译器自动生成一个不带参数的默认(缺省)构造函数动生成一个不带参数的默认(缺省)构造函数,其格式:()()在程序中定义一个对象而没有指明初始化时,则编译器便按缺省构造函数来初始化该对象。使使用缺省构用缺省构造函数对对象初始化时造函数对对象初始化时,将对象的所有数据成员都初始将对象的所有数据成员都初始化为零或空。化为零或空。如在日期类Tdate1的程序中有说明语句:TDatel today,tomorrow;这时编译系统使用缺省构造函数对today,tomorrow第五章进行初始化,使today(0,0,0),tomorrow(0,0,0)。同理,如果一个类中没有定义析构
22、函数时如果一个类中没有定义析构函数时,则编译则编译系统也生成一个默认(缺省)析构函数系统也生成一个默认(缺省)析构函数,其格式如下:即为该类的类名。缺省析构缺省析构函数是一个空函数,函数是一个空函数,只用来释放对象。三、复制三、复制构造函数:构造函数:复制构造函数也是一种特殊的成员函数。是一种特殊的成员函数。第五章1、复制复制构造函数的功能:构造函数的功能:用一个已知的对象来初始化一个被创建的同类的用一个已知的对象来初始化一个被创建的同类的对象。对象。2 2、复制、复制构造函数的特点构造函数的特点:、也是一种构造函数,函数名同类名函数名同类名;、也不被指定返回类型,只有一个参数只有一个参数,并
23、且是对某并且是对某 个对象的引用。个对象的引用。、每个类都必须有一个复制构造函数每个类都必须有一个复制构造函数,其定义格式::(&)函数体函数体 第五章、当一个类中没有定义复制构造函数时,系统将创 建一个默认的复制构造函数。3、一般有三种情况需调用复制构造函数一般有三种情况需调用复制构造函数:、明确表示有一个对象初始化另一个对象,如:Tpoint p2(p1);、对象作为函数实参传递给函数形参时,如:P=f(N);、当对象作为函数的返回值时,如:return R;此时系统将用R来初始化一个匿名对象。第五章例例6 6、利用构造函数、析构函数和复制构造函数重新定 义点类TPoint,并存放在名为t
24、point1.h的头文件中。并分析程序的运行结果。首先建立 tpoint1.h 头文件:class TPoint public:TPoint (int x,int y)X=x;Y=y;TPoint(TPoint&p);TPoint()coutDestructor Called.n;int Xcoord()return X;int Ycoord()return Y;private:int X,Y;;第五章TPointTPoint(TPoint&p)X=p.X;Y=p.Y;coutCopy_initialization Constructor Called.n;主程序:#include#inclu
25、de tpoint1.hvoid main()TPoint P1(5,7);TPoint P2(P1);coutp2=P2.Xcoord,P2.Ycoordendl;第五章 执行该程序后,输出结果如下:Copy_initialization Constructor Called.P2=5,7Destructor Called.Destructor Called.第四节 成员函数的特性 第五章一、内联函数和外联函数:一、内联函数和外联函数:类的成员函数可分为:1 1、内联函数:、内联函数:定义在类体内的成员函数。定义在类体内的成员函数。2 2、外联函数:、外联函数:说明在类体内,定义在类体外的成
26、员函说明在类体内,定义在类体外的成员函 数,数,即函数体的说明部分在类的实现部分。例7、分析程序。class A public:A(int x,int y)X=x;Y=y;int a()return X;/内联函数 int b()return Y;/内联函数 int c();/外联函数 int d();/外联函数第五章 private:int X,Y;inline int Ac()return a()+b();inline int Ad()return c();#includevoid main()A m(3,5);int i=m.d();coutd()return:iendl;第五章 运行程
27、序,结果:d()return:8二、重载性:二、重载性:一般的成员函数可以重载,构造函数可以重载,而析构函数不能重载。例8 分析程序。class M public:M(int x,int y)X=x;Y=y;M(int x)X=x;Y=x*x;int Add(int x,int y);int Add(int x);int Add();int Xout()return X;第五章 int Yout()return Y;private:int X,Y;int M Add(int x,int y)X=x;Y=y;return X+Y;int M Add(int x)X=Y=x;return X+Y;
28、int M Add()return X+Y;第五章#includevoid main()M a(10,20),b(4);couta=a.Xout(),a.Yout()endl;coutb=b.Xout(),b.Yout()endl;int i=a.Add();int j=a.Add(3,9);int k=b.Add(5);coutiendljendlkendl;运行该程序,得到运行结果为:a=10,20b=4,16301210第五章三、设置参数的缺省值:三、设置参数的缺省值:一般成员函数和构造成员函数都可被设置参数的缺省值,这与设置函数参数的默认值的方法是一致的。例例9 9、分析程序。clas
29、s N public:N(int a=3,int b=5,int c=7);int Aout()return A;int Bout()return B;int Cout()return C;private:int A,B,C;N N(int a,int b,int c)第五章A=a;B=b;C=c;#includevoid main()N X,Y(9,11),Z(13,15,17);coutX=X.Aout(),X.Bout(),X.Cout(),endl;coutY=Y.Aout(),Y.Bout(),Y.Cout(),endl;coutZ=Z.Aout(),Z.Bout(),Z.Cout(
30、),endl;运行该程序,得到运行结果为:X=3,5,7Y=9,11,7Z=13,15,17 第五节 静态成员第五章 全局量的可见范围是无法控制的,即在整个程序内都是可见的,在程序的任何地方全局变量都可被更新,如果不小心更新了,就会影响到更新后的程序。所以为了安全起见,尽量不使用全局变量,而使用静静态成员态成员,从而实现多个对象之间的数据共享。从而实现多个对象之间的数据共享。一、静态成员的特点:一、静态成员的特点:1、静态成员是属于类的,而不是属于某个对象的属于类的,而不是属于某个对象的。2、静态成员包含有静态数据成员和静态成员函数含有静态数据成员和静态成员函数两 种。3、静态成员的定义方法是
31、在该成员说明前加上关键字定义方法是在该成员说明前加上关键字 Static Static。第五章二、二、静态数据成员:静态数据成员:1 1、静态数据成员的特点:静态数据成员的特点:、静态数据成员是类的所有对象中共享的成员是类的所有对象中共享的成员,而不 是某个对象的成员,可以实现多个对象之间的数据共可以实现多个对象之间的数据共 享。享。、使用静态数据成员不会破坏隐藏的原则不会破坏隐藏的原则,即保证了安全性。、静态数据成员是同一类中所有对象所公有的,是同一类中所有对象所公有的,对 多个对象来说,静态数据成员只存储一处只存储一处,供所有对 象共用,所以使用静态数据成员可以节省内存。使用静态数据成员可
32、以节省内存。、静态数据成员的值对每个对象都是一样的,但它值对每个对象都是一样的,但它 的值是可以更新的的值是可以更新的。只要对静态数据成员的值更新第五章 一次,保证所有对象存取更新以后的、相同的值,这样可以提高时间效率。2 2、静态数据成员的使用方法和注意事项静态数据成员的使用方法和注意事项:、静态数据成员在定义或说明时前面加关键字在定义或说明时前面加关键字staticstatic 如:class A private:int a,b,c;static static int s;、静态数据成员是静态存储的,必须对它进行初始必须对它进行初始 化化,而且与与一般数据成员初始化不同,初始化在类一般数据
33、成员初始化不同,初始化在类 体外进行体外进行。其格式为::=;如:int A A s=10第五章 格式中:a、初始化时为避免与一般静态变量或对象相混淆,静静 态数据成员名前面不加态数据成员名前面不加staticstatic关键字;关键字;b、初始化时不加该成员的访问权限控制符不加该成员的访问权限控制符 private,public 等;c、静态数据成员是类的成员,而不是对象的成员,因 此,初始化时使用作用域运算符来标明它所属的类;、如果静态数据成员的访问权限允许的话(即public 的成员),可在程序中引用静态数据成员。采用的格 式:例例1010、分析下列程序的输出结果。第五章#include
34、class Myclass public:Myclass(int a,int b,int c);void GetNumber();void GetSum();private:int A,B,C;static int Sum;/在类体内说明静态数据成员在类体内说明静态数据成员Sum;int Myclass Sum=0;/静态数据成员静态数据成员Sum初始化为初始化为0MyclassMyclass(int a,int b,int c)A=a;B=b;C=c;Sum+=A+B+C;第五章void Myclass:GetNumber()coutNumber=A,B,Cendl;void Myclass
35、:GetSum()coutSum=Sumendl;void main()Myclass M(3,7,10),N(14,9,11);M.GetNumber();N.GetNumber();M.GetSum();N.GetSum();第五章执行该程序输出如下结果:Number=3,7,10 Number=14,9,11 Sum=54Sum=54第五章三、静态成员函数:静态成员函数:1 1、静态成员函数的特点:、静态成员函数的特点:静态成员函数和静态数据成员一样,都属于类的属于类的静态成员静态成员,都不是对象成员都不是对象成员。因此,对静态成员的引用对静态成员的引用不需要用对象名。不需要用对象名。2
36、 2、使用静态成员函数的注意事项:使用静态成员函数的注意事项:、在静态成员函数的实现中,可以引用类中说明的可以引用类中说明的 静态成员,而不能直接引用类中说明的非静态成静态成员,而不能直接引用类中说明的非静态成 员,如果要引用非静态成员时员,如果要引用非静态成员时,可通过对象来引用可通过对象来引用。、调用静态成员函数的格式:()例例1111 分析程序的输出结果。第五章#include class M public:M(int a)A=a;B+=a;static void f1(M m);/静态成员函数静态成员函数f1(),其中参数其中参数m是类的对象是类的对象 private:int A;st
37、atic int B;void Mf1(M m)cout“A=”m.Aendl;/静态成员函数通过对象静态成员函数通过对象m来引用类中非静态数据成员来引用类中非静态数据成员 coutB=Bendl;int MB=0;/静态数据成员初始化静态数据成员初始化void main()第五章 M P(5),Q(10);Mf1(P);Mf1(Q);执行该程序后输出结果如下:A=5 B=15 A=10 B=15第六节 友元第五章一、友元的引进及特点:一、友元的引进及特点:1 1、友元引入的原因:、友元引入的原因:类具有封装和信息隐藏的特性,只有类的成员函数才能访问类中的私有成员,而程序中的非成员函数是无法访
38、问类中私有成员的,只可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。为了解决这些问题,提出使用友元。友元有友元有友元友元函数和友元类两种。函数和友元类两种。第五章2 2、友元的特点:、友元的特点:友友元不是成员函数,但是它可以访问类中的私有元不是成员函数,但是它可以访问类中的私有成员,成员,因此它破坏了类的封装性和隐藏性,但是友元提高了程序的运行效率。二、友元函数友元函数:1 1、概念、概念:友元函数:友元函数:是一种定义在类体外的需要
39、在类体内是一种定义在类体外的需要在类体内进行说明的进行说明的普通非成员函数。普通非成员函数。为了与该类的成员函数加以区别,在说明时前面加关键字friend。说明友元函数的方法如下:friendfriend 类型函数名类型函数名(参数表参数表)函数体函数体 第五章2、友元函数的特点:友元函数的特点:能够访问类中私有成员的非成员函数,在在定义和定义和调用上与普通函数一样。调用上与普通函数一样。例例1212、已知两点坐标,求两点距离。#include#include class Point public:Point(double xx,double yy)x=xx;y=yy;void Getxy()
40、;friend double Distance(Point&a,Point&b);private:double x,y;第五章void PointGetxy()cout(x,y)endl;double Distance(Point&a,Point&b)double dx=a.x-b.x;/访问类中私有成员必须通过类的对象访问类中私有成员必须通过类的对象 double dy=a.y-b.y;return sqrt(dx*dx+dy*dy);void main()Point p1(3.0,4.0),p2(6.0,8.0);p1.Getxy();p2.Getxy();double d=Distanc
41、e(p1,p2);coutDistance isdendl;第五章执行该程序输出如下结果:(3.0,4.0)(6.0,8.0)Distance is 5例例1313、分析一个利用友元函数表示时间的例子。#include class Time public:Time(int new-hours,int new-minutes)hours=new-hours;minutes=new minutes;friend void Time12(Time time);friend void Time24(Time time);private:int hours,minutes;第五章 void Time12
42、(Time time)/友元函数的形参为友元函数的形参为Time类的对象类的对象time if(time.hours12)/访问类中私有成员访问类中私有成员hours必须通过类的对象必须通过类的对象time time.hours-=12;couttime.hours:time.minutesPMendl;else couttime.hours:time.minutesAMendl;void Time24(Time time)couttime.hours:time.minutesendl;void main()第五章 Time Time1(20,30),Time2(10,45);Time12(T
43、ime1);Time24(Time1);Time12(Time2);Time24(Time2);运行结果运行结果:8:30PM 20:30 10:45AM 10:45 三、三、友元类友元类:1 1、友元类定义:、友元类定义:在一个类体内,按下列格式说明的类称友元类。在一个类体内,按下列格式说明的类称友元类。friendfriend class class 类名类名;第五章2 2、友元类的特点:、友元类的特点:友元类中的成员函数为其被定义类的友元函数,友元类中的成员函数为其被定义类的友元函数,即当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数。例例14 14 分
44、析一个友元类程序的输出结果。#include class X friend class Y;/说明友元类说明友元类Y public:void Set(int i)x=i;void Display()coutx=x,;couty=yendl;第五章 private:int x;static int y;/y是静态数据成员是静态数据成员;class Y public:Y(int i,int j);void Display();private:X a;/类类Y中的私有成员中的私有成员a是是X类的一个对象类的一个对象;int Xy=1;/为为X类的静态数据成员初始化类的静态数据成员初始化YY(int
45、i,int j)/Y类中的构造函数类中的构造函数Y是是X类的友元函数类的友元函数 a.x=i;Xy=j;第五章void YDisplay()coutx=a.x,;couty=XyM中。4、在使用作用域运算符所限定的该成员中。如,在表 达式AM中。二、二、局部类和嵌套类:局部类和嵌套类:1 1、局部类:局部类:在一个函数体内定义的类称为局部类。在一个函数体内定义的类称为局部类。因为外围作用域中的变量与该局部类的对象无关,所以局部类第五章中只能使用它的外围作用域中的对象和函数进行联系。在定义局部类时需要注意:局部类中不能说明静态局部类中不能说明静态成员函数成员函数,并且所有成员函数都必须是内联函数
46、。并且所有成员函数都必须是内联函数。2 2、嵌套类:嵌套类:在一个类中定义的类称为嵌套类在一个类中定义的类称为嵌套类,而定义嵌套类的而定义嵌套类的类称为外围类。类称为外围类。定义嵌套类的目的在于隐藏类名,减少全局的标识符,从而限制用户能否使用该类建立对象。这样可以提高类的抽象能力,并且强调了两个类(外围类和嵌套类)之间的主从关系。对嵌套类的说明对嵌套类的说明:、从作用域的角度上看,嵌套类被隐藏在外围类之 中,该类名只能在外围类中使用。第五章、从访问权限的角度来看,嵌套类名与它的外围类 的对象成员名具有相同的访问权限规则。、类中的成员函数都必须是内联函数。、嵌套类中说明的成员不是外围类中对象的成
47、员,反 之亦然。嵌套类的成员函数对外围类的成员没有访 问权。反之亦然。、在嵌套类中说明的友元对外围类的成员没有访问 权。、如果嵌套类比较复杂,可以只在外围类中对嵌套 类进行说明,关于嵌套类的详细的内容可在外围类 体外的文件域中进行定义。第八节 对象的生存期 第五章 对象的生存期是指对象从被创建开始到被释放为对象的生存期是指对象从被创建开始到被释放为止的时间。止的时间。按生存期的不同对象可分为三种三种:1 1、局部对象:、局部对象:被定义在一个函数体或程序块内的对象。被定义在一个函数体或程序块内的对象。它的作用域小,生存期也短。2 2、静态对象:、静态对象:被定义在一个文件中的对象。被定义在一个
48、文件中的对象。它的作用域从定义时起到文件结束时止。它的作用域比较大,它的生存期也比较大。3 3、全局对象:、全局对象:被定义在某个文件中的对象。被定义在某个文件中的对象。它的作用域在包含第五章该文件的整个程序中,它的作用域是最大的,它的生存期也是长的。例例1616、不同对象的生存周期。#include#includeclass A public:A(char*st);A();private:char string50;AA(char*st)strcpy(string,st);coutconstructor called for stringendl;第五章AA()coutDestructor
49、called for stringendl;void fun()A FunObject(FunObject);static A staticObject(staticObject);coutIn fun().endl;A GlobalObject(GlobalObject);void main()A MainObject(MainObject);coutIn main(),befor called funn;fun();coutIn main(),after called funn;第五章程序运行结果:constructor called for GlobalObjectconstructor called for MainObjectIn main(),befor called funconstructor called for FunObjectconstructor called for staticObjectIn fun().Destructor called for FunObjectIn main(),after called funDestructor called for MainObjectDestructor called for staticObjectDestructor called for GlobalObject第五章.第五章.第五章.
限制150内