《第4章C程序设计教程与实验指导杨国兴类与对象.ppt》由会员分享,可在线阅读,更多相关《第4章C程序设计教程与实验指导杨国兴类与对象.ppt(64页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第4章C程序设计教程与实验指导杨国兴类与对象 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望第4章类与对象4.1类与对象4.2构造函数与析构函数4.3类的组合4.4友元4.5静态成员4.6对象数组与对象指针4.7this指针4.1 类与对象4.1.1类与对象的概念 对象对象对象对象(object)(object):是现实世界中的客观事物。是现实世界中的客观事物。类类类类(class)(class):是是把具有相同属性的事物划分为一类,从而得出把具有相同属性的事物划
2、分为一类,从而得出的抽象概念。的抽象概念。面向对象程序设计中的面向对象程序设计中的类类,是具有相同属性和服务的,是具有相同属性和服务的一组对象一组对象的集合的集合,它为属于该类的全部对象提供了抽象的描述。,它为属于该类的全部对象提供了抽象的描述。对象对象是是类的实例类的实例,类类是同种是同种对象的抽象对象的抽象。第4章 类与对象 如:如:如:如:确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个具体的对象具体的对象具体的对象具体的对象,而将所有矩形的共同特,而将所有矩形的共同特,而将所有矩形的共同特,而将所有矩形的共同特点抽
3、象出来,就是一个点抽象出来,就是一个点抽象出来,就是一个点抽象出来,就是一个矩形类矩形类矩形类矩形类。这些共有的属性包括这些共有的属性包括这些共有的属性包括这些共有的属性包括颜色颜色颜色颜色 (color)(color),左上角坐标左上角坐标左上角坐标左上角坐标 (left,top)(left,top),长长长长 (length)(length)和和和和宽宽宽宽 (width)(width)等;等;等;等;对这些属性的处理包括对这些属性的处理包括对这些属性的处理包括对这些属性的处理包括改变矩形的颜色改变矩形的颜色改变矩形的颜色改变矩形的颜色 (SetColor)(SetColor)和和和和大小
4、大小大小大小 (SetSize)(SetSize),移移移移动矩形到新的位置动矩形到新的位置动矩形到新的位置动矩形到新的位置 (Move)(Move),绘出矩形绘出矩形绘出矩形绘出矩形 (Draw)(Draw)等。将矩形的这些属性和方法作等。将矩形的这些属性和方法作等。将矩形的这些属性和方法作等。将矩形的这些属性和方法作为一个整体,封装在一起形成一个矩形类。为一个整体,封装在一起形成一个矩形类。为一个整体,封装在一起形成一个矩形类。为一个整体,封装在一起形成一个矩形类。4.1 类与对象4.1.2类的声明 class class 类名类名类名类名private:private:私有数据成员和成员
5、函数;私有数据成员和成员函数;protected:protected:保护数据成员和成员函数;保护数据成员和成员函数;public:public:公有数据成员和成员函数;公有数据成员和成员函数;第4章 类与对象例例4.14.1定义一个长方形类定义一个长方形类CRectCRect,其数据成员包括颜色,左上,其数据成员包括颜色,左上角坐标,长和宽,其函数成员包括改变矩形的颜色角坐标,长和宽,其函数成员包括改变矩形的颜色(SetColor)(SetColor)和大小(和大小(SetSizeSetSize),移动矩形到新的位置(),移动矩形到新的位置(MoveMove),绘出矩),绘出矩形(形(Dra
6、wDraw)。)。classCRectprivate:charcolor10;intleft;inttop;intlength;intwidth;public:voidSetColor(char*c);voidSetSize(intl,intw);voidMove(intt,intl);voidDraw();第4章 类与对象例例4.14.1(续一)(续一)voidCRect:SetColor(char*c)strcpy(color,c);voidCRect:SetSize(intl,intw)length=l;width=w;voidCRect:Move(intt,intl)top=t;lef
7、t=l;voidCRect:Draw()cout矩形左上角坐标为(left,top)endl;cout矩形长和宽分别为length,widthendl;cout矩形的颜色是colorendl;第4章 类与对象域运算符(域运算符(:)用于指出该函数是)用于指出该函数是哪一个类的成员函数,用法:哪一个类的成员函数,用法:类名类名:函数名(参数表)函数名(参数表)例例4.14.1(续二)(续二)voidmain()CRectr;r.SetColor(Red);r.Move(10,20);r.SetSize(100,200);r.Draw();r.Move(50,50);r.SetColor(Blue
8、);r.Draw();第4章 类与对象定义定义CRect类的对象,定义对象的类的对象,定义对象的格式:格式:类名类名 对象名对象名1,对象名,对象名2,访问对象的公有成员,格式为:访问对象的公有成员,格式为:对象名对象名.公有成员函数名(参数表)公有成员函数名(参数表)对象名对象名.公有数据成员名公有数据成员名程序运行结果为:程序运行结果为:矩形左上角坐标为(矩形左上角坐标为(2020,1010)矩形长和宽分别为矩形长和宽分别为100100,200200矩形的颜色是矩形的颜色是RedRed矩形左上角坐标为(矩形左上角坐标为(5050,5050)矩形长和宽分别为矩形长和宽分别为100100,20
9、0200矩形的颜色是矩形的颜色是BlueBlue4.1 类与对象4.1.3成员的访问控制private:private:私有访问权限,只允许类中的成员函数访问,其他函私有访问权限,只允许类中的成员函数访问,其他函数不能访问。数不能访问。protected:protected:保护访问权限,在第保护访问权限,在第7 7章中介绍。章中介绍。public:public:公有访问权限,在任何函数中都可以访问。公有访问权限,在任何函数中都可以访问。例:若主函数中有以下语句,是否正确?例:若主函数中有以下语句,是否正确?CRectr;CRectr;strcpy(r.color,“red”);strcpy(
10、r.color,“red”);r.top=10;r.top=10;r.left=20;r.left=20;第4章 类与对象在主函数中不能访问类的私有成员在主函数中不能访问类的私有成员4.1 类与对象4.1.3成员的访问控制(续)若不指定类中的成员的访问权限,则若不指定类中的成员的访问权限,则默认为私有成员默认为私有成员。类也可以由类也可以由structstruct关键字声明,关键字声明,struststrust与与classclass的区别是:如果的区别是:如果不指定访问权限,前者缺省的访问权限是公有的,而后者是私有不指定访问权限,前者缺省的访问权限是公有的,而后者是私有的。用的。用struc
11、tstruct声明前面的矩形类:声明前面的矩形类:structCRectstructCRect voidSetColor(char*c);voidSetColor(char*c);voidSetSize(intl,intw);voidSetSize(intl,intw);voidMove(intt,intl);voidMove(intt,intl);voidDraw();voidDraw();private:private:charcolor10;charcolor10;intleft;intleft;inttop;inttop;intlength;intlength;intwidth;int
12、width;第4章 类与对象4.1 类与对象4.1.4类的成员函数1.1.类成员函数的定义方式类成员函数的定义方式类成员函数的定义方式类成员函数的定义方式在类外部定义:在类外部定义:如前面定义的长方形类的成员函数如前面定义的长方形类的成员函数一般格式为:一般格式为:函数类型函数类型 类名类名:成员函数名(参数说明)成员函数名(参数说明)函数体函数体在类中定义:在类中定义:如如classCRectclassCRectpublic:public:voidsetcolor(char*c)strcpy(color,c);voidsetcolor(char*c)strcpy(color,c);第4章 类
13、与对象4.1 类与对象4.1.4类的成员函数(续一)2.2.内联成员函数内联成员函数内联成员函数内联成员函数 将成员函数的定义直接写在类中即成为内联成员函数将成员函数的定义直接写在类中即成为内联成员函数在类外定义时用在类外定义时用inlineinline指出:指出:如如:inlinevoidCRect:SetColor(char*c)inlinevoidCRect:SetColor(char*c)strcpy(color,c);strcpy(color,c);第4章 类与对象4.1 类与对象4.1.4类的成员函数(续二)3.3.带默认参数值的成员函数带默认参数值的成员函数带默认参数值的成员函数
14、带默认参数值的成员函数 注意:注意:默认参数只能在声明或定义中的一处给出,即默认参数只能在声明或定义中的一处给出,即如在类中的函数声明已经给出默认参数值:如在类中的函数声明已经给出默认参数值:voidSetSize(intl=100,intw=100);voidSetSize(intl=100,intw=100);则在函数定义时就不能再给出默认值。则在函数定义时就不能再给出默认值。同样如果在定义时给出了默认值:同样如果在定义时给出了默认值:voidCRect:SetSize(intl=100,intw=100)voidCRect:SetSize(intl=100,intw=100)length
15、=l;length=l;width=w;width=w;在声明处就不能再给默认值了。在声明处就不能再给默认值了。第4章 类与对象 返 回4.2 构造函数与析构函数构造函数:对对象进行初始化。构造函数:对对象进行初始化。析构函数:在对象销毁时进行内存释放等清理工作。析构函数:在对象销毁时进行内存释放等清理工作。4.2.1构造函数1.1.构造函数的特点构造函数的特点构造函数的特点构造函数的特点(1)(1)构造函数的函数名与类名相同。构造函数的函数名与类名相同。(2)(2)不能定义构造函数的类型(即不能指明构造函数返回值的不能定义构造函数的类型(即不能指明构造函数返回值的类型)。类型)。(3)(3)
16、构造函数应声明为公有函数。构造函数应声明为公有函数。(4)(4)构造函数不能在程序中调用,在对象创建时,构造函数被构造函数不能在程序中调用,在对象创建时,构造函数被系统自动调用。系统自动调用。2.2.构造函数的作用构造函数的作用构造函数的作用构造函数的作用构造函数的作用就是在对象被创建时利用特定的值构造对象,构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态,使此对象具有区别于其它对象将对象初始化为一个特定的状态,使此对象具有区别于其它对象的特征。的特征。第4章 类与对象例为CRect类添加构造函数class CRectclass CRect private:p
17、rivate:char color10;char color10;public:public:CRect();CRect();CRect(char*c,int t,int left,int len,int wid);CRect(char*c,int t,int left,int len,int wid);void SetColor(char*c);void SetColor(char*c);CRect:CRect()CRect:CRect()strcpy(color,Black);strcpy(color,Black);top=0;top=0;left=0;left=0;length=0;le
18、ngth=0;width=0;width=0;二者是重载函数,二者是重载函数,在定义对象时,在定义对象时,如果不给出参数,就自动调用第一如果不给出参数,就自动调用第一个构造函数,如果给定个构造函数,如果给定5个参数就个参数就自动调用第二个构造函数。自动调用第二个构造函数。第4章 类与对象例为CRect类添加构造函数(续)CRect:CRect(char*c,intt,intlef,intlen,intwid)CRect:CRect(char*c,intt,intlef,intlen,intwid)strcpy(color,c);strcpy(color,c);top=t;top=t;left=
19、lef;left=lef;length=len;length=len;width=wid;width=wid;voidmain()voidmain()CRectr1;CRectr1;/自动调用第一个构造函数自动调用第一个构造函数CRectr2(“red”,10,10,100,100);CRectr2(“red”,10,10,100,100);/自动调用第二个构造函数自动调用第二个构造函数CRectr3(green,200,200,50,50);CRectr3(green,200,200,50,50);/自动调用第二个构造函数自动调用第二个构造函数r1.Draw();r1.Draw();r2.D
20、raw();r2.Draw();r3.Draw();r3.Draw();第4章 类与对象例4.2构造函数的初始化表#include#includeusingnamespacestd;usingnamespacestd;classAclassA private:private:constdoublePI;constdoublePI;intb;intb;int&c;int&c;public:public:A(intx):PI(3.14),c(b)A(intx):PI(3.14),c(b)b=x;b=x;voidOutput()voidOutput()coutPI,b,cendl;coutPI,b,
21、cendl;第4章 类与对象voidmain()voidmain()Ax(10);Ax(10);x.Output();x.Output();程序运行结果:3.14,10,104.2 构造函数与析构函数4.2.2析构函数1.1.析构函数的特点析构函数的特点析构函数的特点析构函数的特点(1)(1)析构函数名字为符号析构函数名字为符号“”加类名。加类名。(2)(2)析构函数没有参数,不能指定返回值类型。析构函数没有参数,不能指定返回值类型。(3)(3)一个类中只能定义一个析构函数,所以析构函数不能重载。一个类中只能定义一个析构函数,所以析构函数不能重载。(4)(4)当一个对象作用域结束时,系统自动调
22、用析构函数。当一个对象作用域结束时,系统自动调用析构函数。如如CRectCRect类的析构函数声明为:类的析构函数声明为:CRect();CRect();定义为:定义为:CRect:CRect()CRect:CRect()2.2.析构函数的作用析构函数的作用析构函数的作用析构函数的作用在删除一个对象前被调用,释放该对象成员的内存空间,以及在删除一个对象前被调用,释放该对象成员的内存空间,以及其它一些清理工作。其它一些清理工作。第4章 类与对象例例4.34.3设计一个简单的字符串类,类中有两个数据成员,分别设计一个简单的字符串类,类中有两个数据成员,分别表示字符串的长度和字符串的内容,有一个构造
23、函数和一个析表示字符串的长度和字符串的内容,有一个构造函数和一个析构函数,函数构函数,函数GetLength()GetLength()返回字符串长度,函数返回字符串长度,函数GetContentsGetContents()()获得字符串的内容,重载函数获得字符串的内容,重载函数SetContents()SetContents()给字符串设置给字符串设置值。值。#include#include using namespace std;class CString private:int length;char*contents;public:CString();/构造函数构造函数 CString(
24、);/析构函数析构函数 int GetLength();void GetContents(char*str);void SetContents(int len,char*cont);void SetContents(char*cont);第4章 类与对象例例4.34.3(续一)(续一)CString:CString()length=0;contents=NULL;cout 字符串对象初始化字符串对象初始化 endl;CString:CString()CString:CString()cout contents cout contents 被销毁被销毁被销毁被销毁 endl;endl;if(co
25、ntents!=NULL)if(contents!=NULL)delete contents;delete contents;int CString:GetLength()int CString:GetLength()return length;return length;void CString:GetContents(char*str)void CString:GetContents(char*str)strcpy(str,contents);strcpy(str,contents);第4章 类与对象例例4.34.3(续二)(续二)void CString:SetContents(int
26、len,char*cont)length=len;if(contents!=NULL)delete contents;contents=new charlen+1;strcpy(contents,cont);cout 两个参数的两个参数的SetContents函数函数 endl;void CString:SetContents(char*cont)length=strlen(cont);if(contents!=NULL)delete contents;contents=new charlength+1;strcpy(contents,cont);cout 一个参数的一个参数的SetConte
27、nts函数函数 endl;第4章 类与对象重载函数重载函数SetContents()都是将要设置的字符串长都是将要设置的字符串长度赋给数据成员度赋给数据成员length,然后判断原来数据成员然后判断原来数据成员contents是否已经有数是否已经有数据(即已经不为空据(即已经不为空NULL了),如果已不为空,则了),如果已不为空,则先释放原来的内存,再根先释放原来的内存,再根据新字符串的长度重新申据新字符串的长度重新申请内存。请内存。例例4.34.3(续三)(续三)void main()CString str1,str2;/两次调用构造函数两次调用构造函数 str1.SetContents(第
28、一个字符串第一个字符串);/调用有一个参数的调用有一个参数的SetContents函数函数 str2.SetContents(20,第二个字符串两个参数第二个字符串两个参数);/调用有两个参数的调用有两个参数的SetContents函数函数 int i=str1.GetLength();char string100;str1.GetContents(string);cout i string endl;i=str2.GetLength();str2.GetContents(string);cout i string endl;第4章 类与对象程序运行结果为:程序运行结果为:字符串对象初始化字符
29、串对象初始化字符串对象初始化字符串对象初始化一个参数的一个参数的SetContentsSetContents函数函数两个参数的两个参数的SetContentsSetContents函数函数1212第一个字符串第一个字符串2020第二个字符串两个参数第二个字符串两个参数第二个字符串两个参数被销毁第二个字符串两个参数被销毁第一个字符串被销毁第一个字符串被销毁4.2 构造函数与析构函数4.2.3拷贝构造函数 拷拷贝贝构构造造函函数数也也是是构构造造函函数数,它它的的作作用用是是用用一一个个已已经经存存在在的的对对象初始化新对象,拷贝构造函数的参数为该类对象的引用。象初始化新对象,拷贝构造函数的参数为
30、该类对象的引用。例例例例4.44.4 设设计计一一个个复复数数类类,两两个个数数据据成成员员分分别别表表示示复复数数的的实实部部(realreal)和和虚虚部部(imagimag),三三个个构构造造函函数数分分别别在在不不同同的的情情况况下下初初始始化化对对象象,函函数数SetSet()设设置置复复数数实实部部和和虚虚部部的的值值,函函数数PrintPrint()输输出复数,函数出复数,函数AddAdd()和函数()和函数SubSub()分别实现复数的加减法运算。()分别实现复数的加减法运算。第4章 类与对象例例4.44.4源程序源程序#include iostream“#include io
31、stream“using namespace std;using namespace std;class CComplex class CComplex private:private:double real;double real;double imag;double imag;public:public:CComplex();CComplex();CComplex(double r,double i);CComplex(double r,double i);CComplex(CComplex&c);CComplex(CComplex&c);/复数类的拷贝构造函数声明复数类的拷贝构造函数声明
32、复数类的拷贝构造函数声明复数类的拷贝构造函数声明void Set(double r,double i);void Set(double r,double i);void Print();void Print();CComplex Add(CComplex c);CComplex Add(CComplex c);CComplex Sub(CComplex c);CComplex Sub(CComplex c);第4章 类与对象例例4.44.4源程序(续一)源程序(续一)CComplex:CComplex()real=0.0;imag=0.0;CComplex:CComplex(double r,
33、double i)real=r;imag=i;CComplex:CComplex(CComplex&c)/复数类的拷贝构造函数定义复数类的拷贝构造函数定义real=c.real;imag=c.imag;/设置复数类的实部和虚部设置复数类的实部和虚部void CComplex:Set(double r,double i)real=r;imag=i;第4章 类与对象例例4.44.4源程序(续二)源程序(续二)/显示复数值显示复数值void CComplex:Print()cout (real ,imag )endl;/返回两个复数的相加结果返回两个复数的相加结果CComplex CComplex:
34、Add(CComplex c)CComplex temp;temp.real=real+c.real;temp.imag=imag+c.imag;return temp;/返回复数相减的结果返回复数相减的结果CComplex CComplex:Sub(CComplex c)CComplex temp;temp.real=real-c.real;temp.imag=imag-c.imag;return temp;第4章 类与对象例例4.44.4源程序(续三)源程序(续三)void main(void)CComplex a,b(3.0,4.0),c;CComplex d(b);/调用复数类的拷贝构
35、造函数调用复数类的拷贝构造函数cout a=;a.Print();cout b=;b.Print();cout d=;d.Print();c=b.Add(d);d=a.Sub(d);cout c=;c.Print();cout d=;d.Print();第4章 类与对象程序运行结果为:程序运行结果为:a=(0,0)a=(0,0)b=(3,4)b=(3,4)d=(3,4)d=(3,4)c=(6,8)c=(6,8)d=(-3,-4)d=(-3,-4)返 回4.3 类的组合类的组合类的组合就是在一个就是在一个类中内嵌其他类的对象类中内嵌其他类的对象作为成员,因为内作为成员,因为内嵌对象是该类对象的组
36、成部分,当创建该对象时,其内嵌对象也嵌对象是该类对象的组成部分,当创建该对象时,其内嵌对象也被自动创建。被自动创建。在在C+C+中是通过构造函数的初始化表为内嵌对象初始化的。组中是通过构造函数的初始化表为内嵌对象初始化的。组合类带有初始化表的构造函数的定义格式为:合类带有初始化表的构造函数的定义格式为:类名类名:构造函数构造函数(参数表参数表):内嵌对象:内嵌对象1(1(参数表参数表1)1),内嵌对象,内嵌对象2(2(参参数表数表2)2),构造函数体构造函数体组合类构造函数的执行顺序为:组合类构造函数的执行顺序为:(1 1)按内嵌对象的声明顺序依次调用内嵌对象的构造函数。)按内嵌对象的声明顺序
37、依次调用内嵌对象的构造函数。(2 2)然后执行组合类本身的构造函数。)然后执行组合类本身的构造函数。第4章 类与对象例例4.54.5点类点类CPointCPoint和线段类和线段类CLineCLine#include#include using namespace std;class CPointpublic:CPoint(int x=0,int y=0)X=x;Y=y;cout CPoint 构造函数被调用构造函数被调用 endl;CPoint(CPoint&p);int GetX()return X;int GetY()return Y;private:int X,Y;第4章 类与对象例例
38、4.54.5点类点类CPointCPoint和线段类和线段类CLineCLine(续一)(续一)CPoint:CPoint(CPoint&p)X=p.X;Y=p.Y;cout CPoint 拷贝构造函数被调用拷贝构造函数被调用 endl;cout (X ,Y )endl;class CLinepublic:CLine(CPoint p1,CPoint p2);float GetDistance();private:CPoint start;CPoint end;第4章 类与对象例例4.54.5点类点类CPointCPoint和线段类和线段类CLineCLine(续二)(续二)CLine:CLi
39、ne(CPoint ps,CPoint pe):start(ps),end(pe)cout CLine 构造函数被调用构造函数被调用 endl;float CLine:GetDistance()double x=double(end.GetX()-start.GetX();double y=double(end.GetY()-start.GetY();return(float)sqrt(x*x+y*y);void main()CPoint p1(1,1),p2(4,5);CLine l(p1,p2);cout The distance is:;cout l.GetDistance()endl;
40、第4章 类与对象程序运行结果为:程序运行结果为:CPointCPoint构造函数被调用构造函数被调用CPointCPoint构造函数被调用构造函数被调用CPointCPoint拷贝构造函数被调用拷贝构造函数被调用(4 4,5 5)CPointCPoint拷贝构造函数被调用拷贝构造函数被调用(1 1,1 1)CPointCPoint拷贝构造函数被调用拷贝构造函数被调用(1 1,1 1)CPointCPoint拷贝构造函数被调用拷贝构造函数被调用(4 4,5 5)CLineCLine构造函数被调用构造函数被调用Thedistanceis:5Thedistanceis:5例例4.54.5点类点类CP
41、ointCPoint和线段类和线段类CLineCLine(续三)(续三)CLine类的对象l的构造过程:第4章 类与对象CLine l(p1,p2)CLine:CLine(CPoint ps,CPoint pe):start(ps),end(pe)CPoint:CPoint(CPoint&p)(1)(2)(3)(4)返 回4.4 友元友元提供了在不同类的成员函数之间、类的成员函数与一般函友元提供了在不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制,友元分为友元函数和友元类。数之间进行数据共享的机制,友元分为友元函数和友元类。友元函数友元函数:一般函数或类的成员函数:一般函数或
42、类的成员函数 友元类友元类:友元类的所有成员函数都自动成为友元函数:友元类的所有成员函数都自动成为友元函数4.4.1友元函数定义友元函数时,只要在函数原型前加入关键字定义友元函数时,只要在函数原型前加入关键字friendfriend,并将,并将函数原型放在类中,格式为:函数原型放在类中,格式为:friendfriend类型标识符类型标识符 友元函数名(参数列表);友元函数名(参数列表);友元函数可以是一个普通函数,也可以是其他类的成员函数,友元函数可以是一个普通函数,也可以是其他类的成员函数,在其函数体中可以通过在其函数体中可以通过对象名直接访问这个类的私有成员对象名直接访问这个类的私有成员。
43、第4章 类与对象例例4.64.6定义点类定义点类CPointCPoint,写一个函数计算两点之间的距离。,写一个函数计算两点之间的距离。#include#include using namespace std;class CPointpublic:CPoint(int x=0,int y=0);int GetX();int GetY();private:int X,Y;CPoint:CPoint(int x,int y)X=x;Y=y;int CPoint:GetX()return X;第4章 类与对象int CPoint:GetY()return Y;double GetDistance(C
44、Point start,CPoint end)int x1,y1,x2,y2;double d;x1=start.GetX();y1=start.GetY();x2=end.GetX();y2=end.GetY();d=sqrt(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);return d;void main()CPoint p1(1,1),p2(4,5);double d;d=GetDistance(p1,p2);cout The distance is:d endl;例例4.64.6(续)(续)将函数GetDistance()声明为CPoint类的友元。将CPoint类修
45、改如下:class CPoint public:CPoint(int x=0,int y=0);int GetX();int GetY();friend double GetDistance(CPoint start,CPoint end);private:int X,Y;函数GetDistance()改写如下:double GetDistance(CPoint start,CPoint end)double d;d=sqrt(end.X-start.X)*(end.X-start.X)+(end.Y-start.Y)*(end.Y-start.Y);return d;第4章 类与对象4.4
46、友元4.4.2友元类如果一个类(如类如果一个类(如类A A)的很多成员函数都需要经常访问另一个)的很多成员函数都需要经常访问另一个类(如类类(如类B B)的私有成员,可以将类)的私有成员,可以将类A A声明为类声明为类B B的友元。的友元。若若A A类为类为B B类的友元类,则类的友元类,则A A类的所有成员函数都是类的所有成员函数都是B B类的友元类的友元函数,都可以访问函数,都可以访问B B类的私有成员。类的私有成员。声明友元类的语法形式为:声明友元类的语法形式为:ClassBClassBfriendclassA;/friendclassA;/声明声明A A为为B B的友元类的友元类;第4
47、章 类与对象例例4.74.7友元类的使用友元类的使用#include using namespace std;class Aprivate:int x;public:void Display()cout x endl;int Getx()return x;friend class B;第4章 类与对象class Bprivate:A a;public:void Set(int i);void Display();void B:Set(int i)a.x=i;void B:Display()cout a.x endl;void main()B b;b.Set(10);b.Display();程序
48、运行结果为:程序运行结果为:10104.4 友元4.4.2友元类(续)注意:注意:注意:注意:友元关系是单向的友元关系是单向的:在上面的例子中,:在上面的例子中,B B类是类是A A类的友元,所类的友元,所以以B B类的成员函数可以访问类的成员函数可以访问A A类的私有成员,但类的私有成员,但A A类不是类不是B B类的友元,类的友元,A A类的成员函数不能访问类的成员函数不能访问B B类的私有成员。类的私有成员。友元关系是不能传递的友元关系是不能传递的:既如果:既如果A A类是类是B B类的友元,类的友元,B B类是类是C C类类的友元,并不能推断的友元,并不能推断A A类是类是C C类的友
49、元。类的友元。第4章 类与对象 返 回4.5 静态成员4.5.1静态数据成员静态数据成员特点:在静态数据成员特点:在每个类中只有一个拷贝每个类中只有一个拷贝,由该类的所有,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享。共享。静态数据成员的定义格式:在定义类的成员时前面加静态数据成员的定义格式:在定义类的成员时前面加staticstaticstaticstatic类型标识符类型标识符静态数据成员名;静态数据成员名;在类的声明中仅仅对静态数据成员进行引用性说明,必须在文在类的声明中仅仅对静态数据成员进行引用性说明,
50、必须在文件作用域的某个地方用类名限定进行定义,这时也可以进行初始件作用域的某个地方用类名限定进行定义,这时也可以进行初始化,格式如下:化,格式如下:类型标识符类型标识符类名类名:静态数据成员名静态数据成员名=初始值;初始值;静态数据成员不属于任何一个对象,可以通过类名直接对它进静态数据成员不属于任何一个对象,可以通过类名直接对它进行访问,一般的用法是:行访问,一般的用法是:类名类名:静态数据成员名静态数据成员名第4章 类与对象例4.8在CStudent类中添加静态数据成员,保存CStudent类的对象总数。#include#include using namespace std;class C