收藏 分销(赏)

谭浩强C程序设计第四.pptx

上传人:快乐****生活 文档编号:8688531 上传时间:2025-02-25 格式:PPTX 页数:103 大小:673.24KB 下载积分:18 金币
下载 相关 举报
谭浩强C程序设计第四.pptx_第1页
第1页 / 共103页
谭浩强C程序设计第四.pptx_第2页
第2页 / 共103页


点击查看更多>>
资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,#,第,7,章,类与对象,C+,语言程序设计教程,第,7,章,类与对象,第,7,章,类与对象,1.,掌握类的定义,会根据需求设计类,;,2.,会根据类创建各种对象;,3.,掌握对象的各种成员的使用方法;,4.,会设计构造函数与拷贝构造函数来初始化对象;理解其调用过程与顺序;,5.,理解浅拷贝与深拷贝的概念;,6.,掌握动态对象以及动态对象数组的建立与释放。,7.,理解类的静态成员的概念;,8.,理解友元函数与友元类的概念;,9.,掌握常对象与常成员的使用;,10.,了解对象在内存中的分布情况。,学习目标,C+,语言程序设计教程,第,7,章,类与对象,7.1,类与对象,在面向过程的结构化程序设计中,程序模块是由函数构成,函数将对数据处理的语句放在函数体内,完成特定的功能,数据则通过函数参数传递进入函数体。,在面向对象的程序设计中,程序模块是由类构成的。类是对逻辑上相关的函数与数据的,封装,,它是对问题的抽象描述。,面向对象的程序设计方法就是运用,面向对象的观点,来对现实世界中的各种问题进行,抽象,,然后用计算机程序来描述并解决该问题,这种描述和处理是通过类与对象实现的。,类,与,对象,是,C+,程序设计中最重要的概念,C+,语言程序设计教程,第,7,章,类与对象,每一个实体都是对象,每个对象都属于一个特定的类型。,在,C+,中对象的类型称为类,(class),。类代表了某一批对象的共性和特征。类是对象的抽象,而对象是类的具体实例,(instance),。正如同结构体类型和结构体变量的关系一样,人们先声明一个结构体类型,然后用它去定义结构体变量。同一个结构体类型可以定义出多个不同的结构体变量。,结构体类型:,struct Student,int num;,char name20;,char sex;,;,Student stud1,,,stud2;,类,:,class Student,int num;,char name20;,char sex;,void display()coutnum:numendl;,coutname:nameendl;,coutsex:sex=0,M=(m=0,S=(s=0,void ShowTime(),coutH:M:S=0,MyClock.M=(M=0,MyClock.S=(S=0,void ShowTime(),coutMyClock.H:;,coutMyClock.M:;,coutMyClock.Sendl;,void main(void),ShowTime();,SetTime(8,30,30);,ShowTime();,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,时钟程序,B,时钟程序,A,运行结果,:,0:0:0 -85893460:-85893460:-5893460,8:30:30 8:30:30,程序解释,:,通过对上述两种方案的程序进行简单的观察,可以发现它们存在下面几点不同:,在程序,A,中,时钟数据用一个结构型的变量存储,对时钟数据的存取通过函数实现。由于存,储时钟数据的是一个全局变量,在任何地方都可见,可以不通过函数单独存取时钟数据。,程序,B,中,只能通过类提供的函数操作时钟。,程序,A,中,数据与对数据操作相互独立,数据作为参数传递给函数。程序,B,中,数据与对数,据的操作构成一个整体。,程序,A,与程序,B,运行的初始结果不同。这是因为在程序,A,中,变量是全局的;在程序,B,中,对,象,(,变量,)MyClock,是函数,main(),中的局部对象。全局变量与局部变量在没有初始化时,取初,值方式不同,这样造成了运行结果不同。将第,23,行移出,main(),外,使之变成全局对象后,,两程序结果完全相同。,在程序,B,中发现,一个以,class,开头的类似结构体的结构,将时钟的数据与对数据进行处理,的函数包括在一起,这就是用,C+,实现的类。,C+,语言程序设计教程,第,7,章,类与对象,7.1.2,类的定义,class,类名,public:,公有数据成员或公有函数成员的定义;,protected:,保护数据成员或保护函数成员的定义;,private:,私有数据成员或私有函数成员的定义;,;,说明,:,关键字,class,表明定义的是一个类;,类名是类的名称,应是一个合法的标识符;,public,、,protected,、,private,为,存取控制属性,(,访问权限,),,用来控制对类的,成员的存取。如果前面没有标明访问权限,,默认访问权限为,private,。,类的成员有数据成员与函数成员两类,类的数据成员和函数成员统称为类的,成员,类的,数据成员,一般用来描述该类对象的属性,称为,属性,;函数成员是描,述类行为,称作方法。函数成员由函数构成,这些作为类成员的函数因此也,叫,成员函数,。,简单讲,类是一个,包含函数,的结构体。因此,类的定义与结构类型的定义相似,其格式如下:,C+,语言程序设计教程,第,7,章,类与对象,7.1.2,类的定义,例如:例,7-1,中定义了一个时钟类,Clock,。,C+,语言程序设计教程,第,7,章,类与对象,在,C+,中也是先声明一个类类型,然后用它去定义若干个同类型的对象。对象就是类类型的一个变量。可以说类是对象的模板,是用来定义对象的一种抽象类型。,类是抽象的,不占用内存,而对象是具体的,占用存储空间。在一开始时弄清对象和类的关系是十分重要的。,类是用户自己指定的类型。如果程序中要用到类类型,必须自己根据需要进行声明,或者使用别人已设计好的类。,C+,标准本身并不提供现成的类的名称、结构和内容。,在,C+,中声明一个类类型和声明一个结构体类型是相似的。,1.,数据成员,类定义中的数据成员描述了,类对象所包含的数据类型,,数据成员的类型可以是,C+,基本数据类型,也可以是构造数据类型。,struct Record,char name20;,int score;,;,class Team,private:,int num;/,基本数据类型,Record*p;/,构造数据类型,;,C+,语言程序设计教程,第,7,章,类与对象,class Team;/,已定义的类,class Grade,Team a;/,使用了已定义的类类型,Grade*p;/,使用正在定义的类类型定义指针成员,Grade /,使用正在定义的类类型定义引用成员,Grade b;/,错误,!,使用了未定义完的类,Record,定义变量,;,注意,:,因为类只是一种类型,类中的数据成员不占内存空间,因此在定义数据成员,时不能给数据成员赋初值。,类的数据成员除了可以使用前面讲述的,C+,类型外,还可以使用已定义完整的,类类型。,在正在定义的类中,由于该类型没有定义完整,所以不能定义该类类型的变,量,只能定义该类类型的指针成员以及该类类型的引用成员。,C+,语言程序设计教程,第,7,章,类与对象,2.,成员函数,作为类成员的成员函数,描述了对类中的数据成员实施的操作,。成员函数的定义、声明格式与非成员函数,(,全局函数,),的格式相同。成员函数可以放在类中定义,也可以放在类外。放在类中定义的成员函数为,内联,(inline),函数,。,Clock,类中的成员函数就是放在类内定义的。,C+,可以在类内声明成员函数的原型,在类外定义函数体。这样做的好处是相当于在类内列了一个,函数功能表,,使我们对类的成员函数的功能一目了然,避免了在各个函数实现的大堆代码中查找函数的定义。在类中声明函数原型的方法与一般函数原型的声明一样,在,类外,定义函数体的格式如下:,:,是类的,作用域分辨符,,用在此处,放在类名后成员函数前,表明后面的成员函数属于前面的那个类。,返回值类型 类名,:,成员函数名,(,形参表,),函数体;,C+,语言程序设计教程,第,7,章,类与对象,Clock,类中的成员函数可以,在类中声明,:,class Clock,private:,int H,M,S;,public:,void SetTime(int h,int m,int s);/,声明成员函数,void ShowTime();/,声明成员函数,;,在类外实现,成员函数如下:,void,Clock,:,SetTime(int h,int m,int s),H=h,M=m,S=s;,;,void,Clock,:,ShowTime(),coutH:M:Sendl;,C+,语言程序设计教程,第,7,章,类与对象,如果要将类外定义的成员函数编译成内联函数,可以在类外定义函数时,函数的返回类型前加上,inline;,下面将,ShowTime(),定义成,内联函数,,与在类内定义成员函数的效果相同。,inline void Clock:ShowTime(),coutH:M:S=0,M=(m=0,S=(s=0,执行:,Clock MyClock;MyClock.ShowTime();,显示结果为:,0:0:0,这是因为建立对象时调用了,Clock(),,各个形参被设成了默认值。,当执行:,Clock MyClock(9,30,45);,MyClock.ShowTime();,显示结果为:,9:30:45,这是因为建立对象时调用了,Clock(9,30,45),C+,语言程序设计教程,第,7,章,类与对象,构造函数是类的一个成员函数,除了具有一般成员函数的特征之外,还归纳出如下特殊的性质:,构造函数的函数名必须与定义它的类同名。,构造函数,没有返回值,。如果在构造函数前加,void,是错误的。,构造函数被声明定义为公有函数。,构造函数在建立对象时,由系统自动调用,。,注意,:由于构造函数可以,重载,,可以定义多个构造函数,在建立对象时根据参数来调用相应的构造函数。如果相应的构造函数,没有定义,,则出错。例如,若定义例,7-1,中的构造函数,而,不是,带默认形参值的构造函数:,Clock,(int h,int m,int s),H=(h=0,M=(m=0,S=(s=0,定义对象,Clock MyClock;,时,调用,Clock(),而,Clock,类没有,Clock(),函数,因而出错。,C+,语言程序设计教程,第,7,章,类与对象,7.2.2,析构函数,自然界万物都是有生有灭,程序中的对象也是一样。对象在定义时诞生,不同生存期的对象在不同的时期消失。在,对象要消失,时,通常有一些善后工作需要做,例如:构造对象时,通过构造函数动态申请了一些内存单元,在对象消失之前就要,释放这些内存单元,。,C+,用什么来保证这些善后清除工作的执行呢?答案是:,析构函数,。,析构函数,(destructor),也译作拆构函数,是在对象消失之前的瞬间自动调用的函数,其形式是,:,构造函数名,(,类名,),前加上一个逻辑非运算符,,以示与构造函数相反。,析构函数与构造函数的作用几乎正好相反,相当于“,逆构造函数,”。析构函数也是类的一个,特殊的公有函数成员,,,C+,语言程序设计教程,第,7,章,类与对象,构造函数名,();,7.2.2,析构函数,析构函数具有以下特点:,析构函数没有任何参数,,不能被重载,,,但可以是虚函数,,,一个类只有一个析构函数。,析构函数,没有返回值,。,析构函数名与类名相同,但在类名前加上一个逻辑非运算符“,”,,以示与构造函数对比区别。,析构函数一般由用户自己定义,,在对象消失时由系统自动调用,,如果用户没有定义析构函数,系统将自动生成一个不做任何事的默认析构函数,。,C+,语言程序设计教程,第,7,章,类与对象,注意,:,在对象消失时的清理工作并不是由析构函数完成,而是靠用户,在析构函数中添加清理语句完成,。,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,/*,*p7_2.cpp *,*,构造函数与析构函数 *,*,/,#include,using namespace std;,class Clock,private:,int H,M,S;,public:,Clock,(int h=0,int m=0,int s=0),H=h,M=m,S=s;,coutconstructor:H:M:Sendl;,C+,语言程序设计教程,第,7,章,类与对象,16,17,18,19,20,21,22,23,24,25,26,27,Clock(),coutdestructor:H:M:Sendl;,;,Clock C1(8,0,0);,Clock C2(9,0,0);,void main(void),Clock C3(10,0,0);,Clock C4(11,0,0);,运行结果,:,constructor:8:0:0,constructor:9:0:0,constructor:10:0:0,constructor:11:0:0,destructor:11:0:0,destructor:10:0:0,C+,语言程序设计教程,第,7,章,类与对象,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,/*,*p7_3.cpp *,*,基本的字符串类 *,*,/,#include,using namespace std;,class,String,private:,char*Str;,int len;,public:,void ShowStr(),coutstring:Str,length:lenendl;,String(),len=0;,Str=NULL;,C+,语言程序设计教程,第,7,章,类与对象,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,String(const char*p),len=strlen(p);,Str=new charlen+1;,strcpy(Str,p);,String(),if(Str!=NULL),delete Str;,Str=NULL;,;,void main(void),char s=ABCDE;,String s1(s);,String s2(123456);,s1.ShowStr();,s2.ShowStr();,运行结果,:,string:ABCDE,length:5,string:123456,length:6,C+,语言程序设计教程,第,7,章,类与对象,7.2.3,拷贝构造函数,拷贝构造函数,是与类名相同,形参是本类的对象的引用的函数,在用,已存在对象,初始化,新建立对象,时调用。,类的拷贝构造函数一般由用户定义,如果用户没有定义拷贝构造函数,系统就会,自动生成,一个默认函数,这个默认拷贝构造函数的功能是把初始值对象的每个数据成员的值,依次复制,到新建立的对象中。因此,也可以说是完成了同类对象的,克隆,(Clone),。这样得到的对象和原对象具有完全相同的数据成员,即完全相同的属性。,C+,语言程序设计教程,第,7,章,类与对象,用户可以也可以,根据实际问题的需要,定义特定的拷贝构造函数来改变缺省拷贝构造函数的行为,以实现同类对象之间数据成员的传递。如果用户自定义了拷贝构造函数,则在用一个类的对象初始化该类的另外一个对象时,,自动调用,自定义的拷贝构造函数。,定义一个拷贝构造函数的一般形式为:,拷贝构造函数在用类的一个对象去初始化该类的另一个对象时调用,以下,三种情况,相当于用一个已存在的对象去初始化新建立的对象,此时,调用拷贝构造函数:,当用类的一个,对象,去初始化该类的另一个,对象,时。,如果函数的,形参是类的对象,,调用函数时,将,对象作为函数实参,传递给函数的形参时。,如果函数的,返回值是类的对象,,函数执行完成,将返回值返回时。,类名(类名,&,对象名),;,C+,语言程序设计教程,第,7,章,类与对象,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,/*,*p7_4.cpp *,*,构造拷贝构造函数 *,*,/,#include,using namespace std;,class,Clock,private:,int H,M,S;,public:,Clock(int h=0,int m=0,int s=0),H=h,M=m,S=s;,coutconstructor:H:M:Sendl;,Clock(),coutdestructor:H:M:Sendl;,C+,语言程序设计教程,第,7,章,类与对象,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,Clock(Clock&p),coutcopy constructor,before call:H:M:Sendl;,H=p.H;,M=p.M;,S=p.S;,void ShowTime(),coutH:M:S,”,运算符访问公有数对象指针名,-,数据成员名,例如:,Clock,*,Cp;,Clock C1(8,0,0);,Clock,*,Cp;,Cp=,&,C1;,Cp,-,ShowTime();,C+,语言程序设计教程,第,7,章,类与对象,类名 *对象指针名;,对象指针名,-,数据成员名,或:,对象指针名,-,成员函数名,(,参数表,),在,C+,中,对象指针可以作为成员函数的形参,一般而言,使用对象指针作为函数的参数要比使用对象作为函数的参数更普遍一些,因为使用对象指针作为函数的参数有如下两点好处:,(1),实现地址传递。,通过在函数调用时将实参对象的地址传递给形参指针对象,使形参指针对象和实参对象指向同一内存地址,这样,对象指针所指向对象的改变也将同样影响着实参对象,从而实现信息的双向传递。,(2),使用对象指针效率高,使用对象指针传递的仅仅是对应实参对象的地址,并不需要实现对象之间的副本拷贝,这样就会减小时空开销,提高运行效率。,C+,语言程序设计教程,第,7,章,类与对象,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,/*,*p7_6.cpp *,*,带时间加法的时钟类 *,*,/,#include,using namespace std;,class Clock,private:,int H,M,S;,public:,void SetTime(int h,int m,int s),H=h,M=m,S=s;,void ShowTime(),coutH:M:SH+H+(Cp-M+M+(Cp-S+S)/60)/60)%24;,M=(Cp-M+M+(Cp-S+S)/60)%60;,S=(Cp-S+S)%60;,C+,语言程序设计教程,第,7,章,类与对象,函数重载,函数原型声明,对象指针,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,void Clock:,TimeAdd,(int h,int m,int s),H=(h+H+(m+M+(s+S)/60)/60)%24;,M=(m+M+(s+S)/60)%60;,S=(s+S)%60;,void Clock:,TimeAdd,(int s),H=(H+(M+(S+s)/60)/60)%24;,M=(M+(S+s)/60)%60;,S=(S+s)%60;,void main(),Clock C1;,Clock C2(8,20,20);,C1.TimeAdd(4000);,C1.ShowTime();,C2.TimeAdd(,C2.ShowTime();,运行结果,:,1:6:40,9:27:0,C+,语言程序设计教程,第,7,章,类与对象,函数重载,函数重载,7.3.2,对象引用,对象引用,就是对某类对象定义一个引用,其实质是通过将被引用对象的地址赋给引用对象,使二者指向,同一内存空间,,这样引用对象就成为了被引用对象的“,别名,”。,对象引用的定义方法与基本数据类型变量引用的定义是一样的。定义一个对象引用,并同时指向一个对象的格式为:,类名,&,对象引用名,=,被引用对象;,C+,语言程序设计教程,第,7,章,类与对象,注意,:,对象引用与被引用对象必须是同类型的。,除非是作为函数参数与函数返回值,对象引用在定义时必须要初始化。,定义一个对象引用并没有定义一个对象,所以不分配任何内存空间,不,调用构造函数。,对象引用的使用格式为:,例如:,Clock C1(8,20,20);,Clock,&,Cr=C1;/,定义了,C1,的对象引用,Cr,。,Cr.ShowTime();/,通过对象引用使用对象的成员,运行结果为:,8:20:20,C+,语言程序设计教程,第,7,章,类与对象,7.3.2,对象引用,对象引用名,.,数据成员名,或:,对象引用名,.,成员函数名,(,参数表,),对象引用的优点:,对象引用通常用作函数的参数,它不仅,具有对象指针的优点,,而且,比对象指针更简洁,更方便,更直观,。将,p7_6.cpp,中添加如下函数:,void Clock:TimeAdd(Clock,&,Cr),H=(Cr.H+H+(Cr.M+M+(Cr.S+S)/60)/60)%24;M=(Cr.M+M+(Cr.S+S)/60)%60;,S=(Cr.S+S)%60;,将,C2.TimeAdd(&,C1,);,替换为,:,C2.TimeAdd(,C1,);,运行结果与,p7_6.cpp,一样。,C+,语言程序设计教程,第,7,章,类与对象,7.3.2,对象引用,对象数组,是以对象为元素的数组。对象数组的定义、赋值、引用与普通数组一样,只是数组元素与普通数组的数组元素不同。,对象数组定义格式如下:,其中,类名指出该数组元素所属的类,常量表达式给出某一维元素的个数。与结构数组不同,对象数组初始化需要使用构造函数完成,以一个大小为,n,的,一维数组,为例,对象数组的,初始化,格式如下:,C+,语言程序设计教程,第,7,章,类与对象,7.3.3,对象数组,类名,对象数组名,常量表达式,n,.,常量表达式,2,常量表达式,1,;,数组名,n=,构造函数,(,数据成员,1,初值,数据成员,2,初值,),构造函数,(,数据成员,1,初值,数据成员,2,初值,),构造函数,(,数据成员,1,初值,数据成员,2,初值,);,注意:,不带初始化表的对象数组,其初始化靠调用,不带参数,的构造函数完成。,以一个,m,维数组为例,对象数组元素的存取格式如下:,C+,语言程序设计教程,第,7,章,类与对象,对象数组名,下标表达式,1,下标表达式,2,下标表达式,m.,数据成员名,或:,对象数组名,下标表达式,1,下标表达式,2,下标表达式,m.,成员函数名,(,参数表,),【,例,7-7】,计算一个班学生某门功课的总评成绩。,分析,:,首先设计一个类,Score,,这个类的数据成员为一个学生的学号、姓名、平时成绩、期末考试成绩,成员函数有求总评成绩、显示成绩。然后,定义一个,对象数组,存储一个班学生的成绩。最后,通过逐一调用,数组元素的成员函数,求每个学生的总评成绩。,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,/*,*p7_7.cpp *,*,求一个班学生某门功课的总评成绩 *,*,/,#include,using namespace std;,const int MaxN=100;,const double Rate=0.6;/,平时成绩比例,class Score,private:,long No;/,学号,char*Name;/,姓名,int Peace;/,平时成绩,int Final;/,期末考试成绩,int Total;/,总评成绩,public:,Score(long=0,char*=NULL,int=0,int=0,int=0);/,构造函数,void Count();/,计算总评成绩,void ShowScore();/,显示成绩,;,C+,语言程序设计教程,第,7,章,类与对象,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,Score:Score(long no,char,*,name,int peace,int final,int total),/,构造函数,No=no;,Name=name;,Peace=peace;,Final=final;,Total=total;,void Score:Count(),Total=Peace*Rate+Final*(1-Rate)+0.5;,void Score:ShowScore(),coutNotNametPeacetFinaltTotalendl;,C+,语言程序设计教程,第,7,章,类与对象,38,39,40,41,42,43,44,45,46,47,48,49,50,void main(),Score ClassScore13;,Score ClassScore23=Score(200607001,Tom,80,79),Score(200607002,John,90,85),Score(200607003,Wilson,70,55);,for(int i=0;i3;i+),ClassScore2i.Count();,for(i=0;iShowTime();/,结果为,0:0:0,Cp=new Clock(8,0,0);/,建立动态对象,调用构造函数,Clock(int,int,int),Cp-ShowTime();/,结果为,8:0:0,C+,语言程序设计教程,第,7,章,类与对象,7.3.4,动态对象,注意,:,函数体内的局部对象在函数调用时建立,在函数调用完后消失;全局对象则在程序执行时建立,执行完成后才消失;这些对象在何时建立,何时消失是,C+,规定好了的,不是编程者能控制的。,在堆中建立的动态对象不能自动消失,需要使用,delete,语句删除对象,格式为:,在删除动态对象时,释放堆中的内存空间,在对象消失时,调用析构函数。,例如:,delete,Cp;/,删除,Cp,指向的动态对象,动态对象的一个重要的使用方面是用动态对象组成动态对象数组,建立一个一维动态对象数组的格式为:,删除一个动态对象数组的格式为:,在建立动态对象数组时,要调用构造函数,调用的次数与数组的大小相同;删除对象数组时,要调用析构函数,调用次数与数组的大小相同。,C+,语言程序设计教程,第,7,章,类与对象,delete,对象指针;,对象指针,=,new,类名,数组大小,;,delete,对象指针;,将,p7_7.cpp,改为用动态对象数组实现如下:,C+,语言程序设计教程,第,7,章,类与对象,7.3.4,动态对象,Score:SetScore(long no,char*name,int peace,int final,int total),No=no;,Name=name;,Peace=peace;,Final=final;,Total=total;,将,p7_7.cpp,改为用动态对象数组实现如下:,C+,语言程序设计教程,第,7,章,类与对象,SetScore(),函数为动态数组设置初值。,void main(),Score*ClassScore;,ClassScore=new Score 3;,ClassScore0.SetScore(200607001,Tom,80,79),ClassScore1.SetScore(200607002,John,90,85),ClassScore2.SetScore(200607003,Wilson,70,55);,for(int i=0;i3;i+),ClassScorei.Count();,for(i=0;iH=h,this-M=m,this-S=s;,(*this).H=h,(*this).M=m,(*this).S=s;,/,语句,3,、,4,、,5,是等效的,为了与类的数据成员,H,、,M,、,S,区别,将,SetTime,的形参名设为,h,、,m,、,s,。如果使用,this,指针,就可以凭,this,指针区分本对象的数据成员与其他变量。,系统利用,this,指针明确指出成员函数当前操作的数据成员所属的对象。实际上,当一个对象调用其成员函数时,编译器先将该对象的地址赋给,this,指针,然后调用成员函数,这样成员函数对对象的数据成员进行操作时,就,隐含,使用了,this,指针。,一般而言,通常,不直接使用,this,指针来引用对象成员,但在某些少数情况下,可以使用,this,指针,如:重载某些运算符以实现对象的连续赋值等。,C+,语言程序设计教程,第,7,章,类与对象,1,2,3,4,/,使用,this,指针,重新设计,的,SetTime(),成员函数如下:,void Clock:SetTime(int H,int M,int S),this-H=H,this-M=M,this-S=S;,注意,:,this,指针不是调用对象的名称,而是指向调用对象的指针的名称。,this,的值不能改变,它总是指向当前调用对象。,7.3.6,对象组合,组合概念体现的是一种,包含与被包含,的关系,在语义上表现为“,is part of,”,的关系,即在逻辑上,A,是,B,的一部分。,在,C+,程序设计中,类的组合用来描述一类复杂的对象,在类的定义中,它的某些属性,往往是另一个类的对象,而不是像整型、浮点型之类的简单数据类型,也就是“一个类内嵌其它类的对象作为成员”,将对象嵌入到类中的这样一种描述,复杂类,的方法,我们称之为“类的组合”,一个含有其他类对象的类称为,组合类,,组合类的对象称为,组合对象,。,组合类定义的步骤为:,先,定义成员类,,再,定义组合类。,C+,语言程序设计教程,第,7,章,类与对象,7.3.6,对象组合,【,例,7-8】,计算某次火车的旅途时间。,分析,:某次火车有车次、起点站、终点站、出发时间、到达时间。前面定义的,Clock,类正具有时间特性,因此,可以利用,Clock,对象组合成一个火车旅途类,TrainTrip,。假定火车均为,24,小时内到达,旅途时间为到达时间减出发时间。,用空方框表示类,灰框表示对象,组合类可以表示为空框包含灰框。设计,TrainTrip,类的示意图与成员构成图如图,7-4,:,C+,语言程序设计教程,第,7,章,类与对象,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,/*,*p7_8.cpp *,*,计算火车旅途时间的组合类 *,*,/,#include,using namespace std;,class Clock,private:,int H,M,S;,public:,void ShowTime(),coutH:M:SH=H,this-M=M,this-S=S;,Clock(int H=0,int M=0,int S=0),this-H=H,this-M=M,this-S=S;,C+,语言程序设计教程,第,7,章,类与对象,Clock,类,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,int GetH(),return H;,int GetM(),return M;,int GetS(),return S;,;,class TrainTrip,private:,char*TrainNo;/,车次,Clock StartTime;/,出发时间,Clock EndTime;/,到达时间,public:,TrainTrip(char*TrainNo,Clock S,Clock E),this-TrainNo=TrainNo;,StartTime=S;,EndTime=E;,C+,语言程序设计教程,第,7,章,类与对象,组合类,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,Clock TripTime(),int tH,tM,tS;/,临时存储小时、分、秒数,int carry=0;/,借位,Clock tTime;/,临时存储时间,(tS=EndTime.GetS()-StartTime.GetS()0,?,carry=0,:,tS+=60,carry=1;,(tM=EndTime.GetM()-StartTime.GetM()-carry)0?carry=0:tM+=60,carry=1;,(tH=EndTime.GetH()-StartTime.GetH()-carry)0?carry=0:tH+=24;,tTime.SetTime(tH,tM,tS);,return tTime;,;,void main(),Clock C1(8,10,10),C2(6,1,2);/,定义,Clock,类的对象,Clock C3;/,定义,Clock,类对象,存储结果,TrainTrip T1(K16,C1,C2);/,定义,TrainTrip,对象,C3=T1.TripTime();,C3.ShowTime();,运行结果,:,21:50:52,C+,语言程序设计教程,第,7,章,类与对象,组合对象及其初始化,C+,为组合对象提供了初始化机制:在定义组合类的构造函数,可以携带初始化表,其格式如下,C+,语言程序设计教程,第,7,章,类与对象,组合类名(形参表):成员对象,1(,子形参表,1),,成员对象,2(,子形参表,2),,,成员对象初始化表,建立对象时,调用组合类的构造函数;在调用组合类的构造函数时,先调用各个成员对象的构造函数,成员对象的初值从初始化列表中取得。这样,实际上是通过成员类的构造函数对成员对象进行初始化,初始化值在初始化表中提供。,为组合类定义了带初始化表的构造函数后,在建立组合对象同时为对象提供初值的格式如下,:,类名 对象名(实参表),;,C+,语言程序设计教程,第,7,章,类与对象,成员对象初始化表,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,/,使用初始化列表,将,p7_8.cpp,修改成,p7_8a.cpp,其中的构造函数修改如下:,TrainTrip(char*TrainNo,int SH,int SM,int SS,int EH,int EM,int ES),:,EndTime(EH,EM,ES),StartTime(SH,SM,SS),this-TrainNo=TrainNo;,/,定义组合对象的程序修改如下:,void main(),Clock C3;/,定义,Clock,类对象,存储结果,TrainTrip T1(K16,8,10,10,6,1,2);/,定义,TrainTrip,对象,C3=T1.TripTime();,C3.ShowTime();,注意,:,初始化列表既不能决定是否调用成员对象的构造函数,也不能决定调用构造函数的顺序,成员对象调用顺序由成员对象定义的顺序决定。初始化列表只是提供调用成员对象构造函数的参数,组合对象的构造函数,:,在定义一个组合类的对象时,不仅它自身的构造函数将被调用,而且还将调用其成员对象的构造函数,调用先后顺序为:,成员对象按照在其组合类的声明中出现的次序,依次调用各自的构造函数,而不是按初始化列表中的顺序。如果建立组合类的成员对象时没有指定对象的初始值,则自动调用默认的构造函数。,组合类对象调用组合类构造函数。,调用析构函数,析构函数的调用顺序与构造函数正好相反。,C+,语言程序设计教程,第,7,章,类与对象,7.4,静态成员,一个类对象的,public,成员可被本类的其他对象
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服