第0章关于类和对象的进一步讨论课件

上传人:沈*** 文档编号:241638664 上传时间:2024-07-12 格式:PPT 页数:108 大小:1.24MB
返回 下载 相关 举报
第0章关于类和对象的进一步讨论课件_第1页
第1页 / 共108页
第0章关于类和对象的进一步讨论课件_第2页
第2页 / 共108页
第0章关于类和对象的进一步讨论课件_第3页
第3页 / 共108页
点击查看更多>>
资源描述
LogoLogoAdd Your Company Slogan第第9章章 关于类和对象的进一步讨论关于类和对象的进一步讨论C+程序程序设计本章内容本章内容9.1 9.1 构造函数构造函数9.2 9.2 析构函数析构函数9.3 9.3 调用构造函数和析构函数的顺序调用构造函数和析构函数的顺序9.4 9.4 对象数组对象数组9.5 9.5 对象指针对象指针9.6 9.6 共用数据的保护共用数据的保护9.7 9.7 对象的动态建立和释放对象的动态建立和释放9.8 9.8 对象的赋值和复制对象的赋值和复制9.9 9.9 静态成员静态成员9.10 9.10 友元友元9.11 9.11 类模板类模板Logo9.1 构造函数构造函数 在建立一个对象时,常常需要作某些初始化的在建立一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。如果一个数据成员工作,例如对数据成员赋初值。如果一个数据成员未被赋值,则它的值是不可预知的,未被赋值,则它的值是不可预知的,对象是一个实对象是一个实体,它反映了客观事物的属性体,它反映了客观事物的属性(例如时钟的时、分、例如时钟的时、分、秒的值秒的值),是应该有确定的值的是应该有确定的值的。9.1.1 对象的初始化对象的初始化Logo9.1.1 对象的初始化对象的初始化类的公用成员可以在定义对象时对数据成员进行初始化。在一个花括号内顺类的公用成员可以在定义对象时对数据成员进行初始化。在一个花括号内顺序列出各公用数据成员的值,两个值之间用逗号分隔。序列出各公用数据成员的值,两个值之间用逗号分隔。如果数据成员是私有的,或者类中有如果数据成员是私有的,或者类中有private或或protected的成员,就不的成员,就不能用这种方法初始化。能用这种方法初始化。class Timeclass Time public:public:/声声明明为公用成公用成员 intint hour;hour;intint minute;minute;intint sec;sec;TimeTime t1t1=14,56,30;=14,56,30;/将将t1t1初始化初始化为14:56:3014:56:30Logo9.1.2 构造函数的作用构造函数的作用构造函数的作用:构造函数的作用:解决对象中解决对象中私有成员私有成员的初始化问题。的初始化问题。u构造函数构造函数是一种特殊的成员函数,与其他成员函数不同,是一种特殊的成员函数,与其他成员函数不同,不需要不需要用户来调用它,而是在建立对象时自动执行。用户来调用它,而是在建立对象时自动执行。u构造函数的名字构造函数的名字必须与类名同名必须与类名同名,而不能由用户任意命名,以便,而不能由用户任意命名,以便编译系统能识别它并把它作为构造函数处理。编译系统能识别它并把它作为构造函数处理。u构造函数构造函数不具有任何类型,不返回任何值不具有任何类型,不返回任何值。u构造函数构造函数的功能的功能是由用户定义的是由用户定义的,用户根据初始化的要求设计函,用户根据初始化的要求设计函数体和函数参数。数体和函数参数。如果用户自己如果用户自己没有定义构造函数没有定义构造函数,则,则C+C+系统系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作。没有参数,不执行初始化操作。构造函数与成员函数有什么不同?构造函数与成员函数有什么不同?Logo例例9.1 9.1 在例在例8.38.3基础上定义构造成员函数。基础上定义构造成员函数。1.1.#include include 2.2.using namespace std;using namespace std;3.3.class class TimeTime4.4.5.5.public:public:6.6.Time()Time()/定义构造成员函数,函数名与类名相同定义构造成员函数,函数名与类名相同7.7.hour=0;/hour=0;/利用构造函数对对象中的数据成员赋初值利用构造函数对对象中的数据成员赋初值8.8.minute=0;minute=0;9.9.sec=0;sec=0;10.10.11.11.void void set_timeset_time();/();/函数声明函数声明12.12.void void show_timeshow_time();/();/函数声明函数声明13.13.private:private:14.14.intint hour;/hour;/私有数据成员私有数据成员15.15.intint minute;minute;16.16.intint sec;sec;17.17.;Logovoid void Timeset_timeTimeset_time()()cincinhour;hour;cincinminute;minute;cincinsec;sec;void void Timeshow_timeTimeshow_time()()coutcouthour:minute:sechour:minute:secendlendl;intint main()main()Time t1;Time t1;/建立建立对象象t1t1,同同时调用用构构造函造函数数t1.Time()t1.Time()t1.set_time();/t1.set_time();/对t1t1的的数数据成据成员赋值t1.show_time();/t1.show_time();/显示示t1t1的的数数据成据成员的的值 Time t2;Time t2;/建立建立对象象t2t2,同同时调用用构构造函造函数数t2.Time()t2.Time()t2.show_time();/t2.show_time();/显示示t2t2的的数数据成据成员的的值return 0;return 0;Logo9.1.2 构造函数的作用构造函数的作用注:注:上面是在类内定义构造函数的,也可以只在类内对构造函数上面是在类内定义构造函数的,也可以只在类内对构造函数进行声明而在类外定义构造函数。进行声明而在类外定义构造函数。在类内声明构造函数:在类内声明构造函数:Time();在类外定义构造函数:在类外定义构造函数:Time Time()/在类外定义构造成员函数,要加上类名在类外定义构造成员函数,要加上类名Time和域限定符和域限定符“”hour=0;minute=0;sec=0;此处两个此处两个Time的含义不同。的含义不同。Logo9.1.3 带参数的构造函数带参数的构造函数 在例在例9.1中构造函数不带参数,在函数体中对中构造函数不带参数,在函数体中对数据成员赋初值。这种方式使该类的每一个对象数据成员赋初值。这种方式使该类的每一个对象都得到同一组初值都得到同一组初值(例如例例如例9.1中各数据成员的初中各数据成员的初值均为值均为0)。但是有时用户希望对不同的对象赋予但是有时用户希望对不同的对象赋予不同的初值。不同的初值。可以采用带参数的构造函数,在调用不同对象可以采用带参数的构造函数,在调用不同对象的构造函数时,从外面将不同的数据传递给构造的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化。函数,以实现不同的初始化。Logo9.1.3 带参数的构造函数带参数的构造函数构造函数首部的一般格式为:构造函数首部的一般格式为:构造函数名构造函数名(类型类型 1 形参形参1,类型类型2 形参形参2,)因为用户是不能调用构造函数的,因此无法采用常因为用户是不能调用构造函数的,因此无法采用常规的调用函数的方法给出实参规的调用函数的方法给出实参。实参是在定义对象时给实参是在定义对象时给出的。出的。类名类名 对象名对象名(实参实参1,实参实参2,);Logo9.1.3 带参数的构造函数带参数的构造函数 例例9.2:有两个长方柱,其长、宽、高分别为:有两个长方柱,其长、宽、高分别为:(1)12,20,25;(2)10,14,20。求它们的体积。编。求它们的体积。编一个基于对象的程序,一个基于对象的程序,在类中用带参数的构造函在类中用带参数的构造函数对对象初始化数对对象初始化。Logo1.1.#include include 2.2.using namespace std;using namespace std;3.3.classclass BoxBox4.4.public:public:5.5.BoxBox(int,int,int(int,int,int);/);/声明带参数的构造函数声明带参数的构造函数6.6.intint volume();/volume();/声明计算体积的函数声明计算体积的函数7.7.private:private:8.8.intint height;height;9.9.intint width;width;10.10.intint length;length;11.11.;12.12.BoxBox BoxBox(int(int h,inth,int w,intw,int lenlen)/)/在类外定义带参数的构造函数在类外定义带参数的构造函数13.13.height=h;height=h;14.14.width=w;width=w;15.15.length=length=lenlen;16.16.Logo17.17.intint BoxvolumeBoxvolume()/()/定定义计算体算体积的函的函数数18.18.return(heightreturn(height*width*length);*width*length);19.19.20.20.intint main()main()21.21.22.22.BoxBox box1box1(12,25,30);(12,25,30);/建立建立对象象box1box1,并并指定指定box1box1长、宽、高的、高的值23.23.coutcoutThe volume of box1 is The volume of box1 is box1.box1.volume()volume()endlendl;24.24.BoxBox box2box2(15,30,21);(15,30,21);/建立建立对象象box2box2,并并指定指定box2box2长、宽、高的、高的值25.25.coutcoutThe volume of box2 is The volume of box2 is box2.box2.volume()volume()endlendl;26.26.return 0;return 0;27.27.(1 1)带参数的构造函数中的形参,其对应的实参在定义对象时给定。)带参数的构造函数中的形参,其对应的实参在定义对象时给定。(2 2)用用这种方法可以方便地实现对不同的对象进行不同的初始。这种方法可以方便地实现对不同的对象进行不同的初始。Logo9.1.4 用参数初始化表对数据成员初始化用参数初始化表对数据成员初始化 在在9.1.3节中介绍的是在构造函数的函数体内通过节中介绍的是在构造函数的函数体内通过赋值语句对数据成员实现初始化。赋值语句对数据成员实现初始化。C+还提供另一种还提供另一种初始化数据成员的方法初始化数据成员的方法参数初始化表来实现对数参数初始化表来实现对数据成员的初始化。据成员的初始化。这种方法不在函数体内对数据成员这种方法不在函数体内对数据成员初始化,而是在函数首部实现。例如例初始化,而是在函数首部实现。例如例9.2中定义构中定义构造函数可以改用以下形式:造函数可以改用以下形式:Box Box(int h,int w,int len):height(h),width(w),length(len)这种写法方便、简练,尤其当需要初始化的数据这种写法方便、简练,尤其当需要初始化的数据成员较多时更显其优越性。甚至可以直接在类体中成员较多时更显其优越性。甚至可以直接在类体中(而而不是在类外不是在类外)定义构造函数。定义构造函数。Logo9.1.5 构造函数的重载构造函数的重载 在一个类中可以定义多个构造函数,以便对类在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法,供用户选用。这些对象提供不同的初始化的方法,供用户选用。这些构造函数具有相同的名字,而构造函数具有相同的名字,而参数的个数或参数的参数的个数或参数的类型不相同类型不相同。这称为构造函数的重载。这称为构造函数的重载。例例9.3:在例在例9.2的基础上,定义两个构造函数,其中的基础上,定义两个构造函数,其中一个无参数,一个有参数。一个无参数,一个有参数。Logo1.1.#include include 2.2.using namespace std;using namespace std;3.3.classclass BoxBox4.4.public:public:5.5.Box();Box();/声明一个无参的构造函数声明一个无参的构造函数6.6.Box(intBox(int h,inth,int w,intw,int len):height(h),width(w),length(lenlen):height(h),width(w),length(len)/声声明一个有参的构造函数,用参数的初始化表对数据成员初始化明一个有参的构造函数,用参数的初始化表对数据成员初始化7.7.intint volume();volume();8.8.private:private:9.9.intint height;height;10.10.intint width;width;11.11.intint length;length;12.12.;13.13.BoxBox BoxBox()()/定义一个无参的构造函数定义一个无参的构造函数14.14.height=10;height=10;15.15.width=10;width=10;16.16.length=10;length=10;17.17.Logo18.18.intint BoxvolumeBoxvolume()()19.19.return(heightreturn(height*width*length);*width*length);20.20.21.21.intint main()main()22.22.23.23.BoxBox box1;box1;/建立建立对象象box1,box1,不指定不指定实参参24.24.coutcoutThe volume of box1 is box1.volume(The volume of box1 is box1.volume()endlendl;25.25.BoxBox box2box2(15,30,25);(15,30,25);/建立建立对象象box2,box2,指定指定3 3个个实参参26.26.coutcoutThe volume of box2 is box2.volume(The volume of box2 is box2.volume()endlendl;27.27.return 0;return 0;28.28.Logo9.1.5 构造函数的重载构造函数的重载说明:说明:(1)调用构造函数时不必给出实参的构造函数,称为默调用构造函数时不必给出实参的构造函数,称为默认构造函数,显然认构造函数,显然无参的构造函数属于默认构造函数无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数一个类只能有一个默认构造函数。(2)如果在建立对象时选用的是无参构造函数,应注意如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。正确书写定义对象的语句。(3)尽管在一个类中可以包含多个构造函数,但是尽管在一个类中可以包含多个构造函数,但是对于对于每一个对象来说,建立对象时只执行其中一个构造函每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行数,并非每个构造函数都被执行。Logo9.1.6 使用默认参数的构造函数使用默认参数的构造函数 构造函数中参数的值既可以通过实参传递,也可构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。译系统就使形参取默认值。在第在第4章第章第4.8节中介绍过在函数中可以使用有默节中介绍过在函数中可以使用有默认值的参数。在构造函数中也可以采用这样的方法来认值的参数。在构造函数中也可以采用这样的方法来实现初始化。实现初始化。例例9.3的问题也可以使用包含默认参数的构造函数的问题也可以使用包含默认参数的构造函数来处理。来处理。例例9.4 将例将例9.3程序中的构造函数改用含默认值的程序中的构造函数改用含默认值的参数,长、宽、高的默认值均为参数,长、宽、高的默认值均为10。在例在例9.3程序的基础上改写如下:程序的基础上改写如下:Logo#include include using namespace std;using namespace std;classclass BoxBox public:public:BoxBox(int(int h=10,int w=10,int h=10,int w=10,int lenlen=10);=10);/在声明构造函数时在声明构造函数时指定默认参数指定默认参数intint volume();volume();private:private:intint height;height;intint width;width;intint length;length;BoxBox BoxBox(int(int h,inth,int w,intw,int lenlen)/在定义函数时可以不指定默认参数在定义函数时可以不指定默认参数 height=h;height=h;width=w;width=w;length=length=lenlen;Logointint BoxvolumeBoxvolume()()return(heightreturn(height*width*length);*width*length);intint main()main()Box box1;Box box1;/没没有有给实参参 coutcoutThe volume of box1 is box1.volume(The volume of box1 is box1.volume()endlendl;Box box2(15);Box box2(15);/只只给定一定一个个实参参coutcoutThe volume of box2 is box2.volume(The volume of box2 is box2.volume()endlendl;Box box3(15,30);Box box3(15,30);/只只给定定2 2个个实参参coutcoutThe volume of box3 is box3.volume(The volume of box3 is box3.volume()endlendl;Box box4(15,30,20);Box box4(15,30,20);/给定定3 3个个实参参coutcoutThe volume of box4 is box4.volume(The volume of box4 is box4.volume()endlendl;return 0;return 0;Logo9.1.6 使用默认参数的构造函数使用默认参数的构造函数说明:说明:(1)应该在声明构造函数时指定默认值,而不能只在定义构造函应该在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。数时指定默认值。(2)程序第程序第5行在声明构造函数时,形参名可以省略。行在声明构造函数时,形参名可以省略。(3)如果构造函数的全部参数都指定了默认值,则在定义对象时如果构造函数的全部参数都指定了默认值,则在定义对象时可以给一个或几个实参,也可以不给出实参。可以给一个或几个实参,也可以不给出实参。(4)在一个类中定义了全部是默认参数的构造函数后,不能再定在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数。义重载构造函数。Logo1.1.#include#include 2.2.using namespace std;using namespace std;3.3.classclass DateDate4.4.public:public:5.5.Date(int,int,intDate(int,int,int););6.6.Date(int,intDate(int,int););7.7.Date(intDate(int););8.8.Date();Date();9.9.void display();void display();10.10.private:private:11.11.intint month;month;12.12.intint day;day;13.13.intint year;year;14.14.;P310 P310 习题2 2Logo15.15.Date:Date(intDate:Date(int m,intm,int d,intd,int y):month(m),day(d),year(yy):month(m),day(d),year(y)16.16.17.17.Date:Date(intDate:Date(int m,intm,int d):month(m),day(dd):month(m),day(d)18.18.year=2005;year=2005;19.19.Date:Date(intDate:Date(int m):month(mm):month(m)20.20.day=1;day=1;21.21.year=2005;year=2005;22.22.Date:DateDate:Date()()23.23.24.24.month=1;month=1;25.25.day=1;day=1;26.26.year=2005year=2005;27.27.28.28.void void Date:displayDate:display()()29.29.coutcoutmonth/day/yearmonth/day/yearendlendl;Logo30.30.intint main()main()31.31.32.32.Date d1(10,13,2005);Date d1(10,13,2005);33.33.Date d2(12,30);Date d2(12,30);34.34.Date d3(10);Date d3(10);35.35.Date d4;Date d4;36.36.d1.display();d1.display();37.37.d2.display();d2.display();38.38.d3.display();d3.display();39.39.d4.display();d4.display();40.40.return 0;return 0;41.41.Logo9.2 析构函数析构函数 析构函数析构函数(destructor)也是一个特殊的成员函数,也是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加它的作用与构造函数相反,它的名字是类名的前面加一个一个“”符号。符号。在在C+中中“”是位取反运算符,是位取反运算符,从这点也可以想到:从这点也可以想到:析构函数是与构造函数作用相析构函数是与构造函数作用相反的函数。反的函数。析构函数的作用:析构函数的作用:释放对象释放对象Logo9.2 析构函数析构函数 当对象的生命期结束时,会自动执行析构函数。当对象的生命期结束时,会自动执行析构函数。具体地说如果具体地说如果出现以下几种情况,程序就会执行析构函数:出现以下几种情况,程序就会执行析构函数:如果在一个函数中定义了一个对象如果在一个函数中定义了一个对象(它是自动局部对象它是自动局部对象),当这个函数被调用结束时,对象应该释放,在对象释放前自动当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。执行析构函数。static局部对象在函数调用结束时对象并不释放,因此也局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在不调用析构函数,只在main函数结束或调用函数结束或调用exit函数结束程函数结束程序时,才调用序时,才调用static局部对象的析构函数。局部对象的析构函数。如果定义了一个全局对象,则在程序的流程离开其作用域如果定义了一个全局对象,则在程序的流程离开其作用域时时(如如main函数结束或调用函数结束或调用exit函数函数)时,调用该全局对象的时,调用该全局对象的析构函数。析构函数。如果用如果用new运算符动态地建立了一个对象,当用运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。运算符释放该对象时,先调用该对象的析构函数。Logo9.2 析构函数析构函数注意:注意:析构函数的作用并不是删除对象,而是在撤销对析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存象占用的内存之前完成一些清理工作,使这部分内存可以被程序分配给新对象使用。可以被程序分配给新对象使用。程序设计者事先设计程序设计者事先设计好析构函数,以完成所需的功能,只要好析构函数,以完成所需的功能,只要对象的生命期对象的生命期结束,程序就自动执行析构函数来完成这些工作。结束,程序就自动执行析构函数来完成这些工作。析构函数析构函数不返回任何值,没有函数类型,也没有不返回任何值,没有函数类型,也没有函数参数。因此它函数参数。因此它不能被重载不能被重载。一个类一个类可以有多个构可以有多个构造函数,但造函数,但只能有一个析构函数只能有一个析构函数。例例9.5 包含构造函数和析构函数的包含构造函数和析构函数的C+程序。程序。Logo#includeinclude#include#include using namespace std;using namespace std;classclass Student Student /声明声明StudentStudent类类 public:public:student(intstudent(int n,stringn,string nam,charnam,char s)s)/定义构造函数定义构造函数 num=n;num=n;name=name=namnam;sex=s;sex=s;coutcoutConstructor called.Constructor called.endlendl;/;/输出有关信息输出有关信息 Student()Student()/定义析构函数定义析构函数 coutcoutDestructor called.Destructor called.endlendl;/输出有关信息输出有关信息Logovoid display()/void display()/定定义成成员函函数数 coutcoutnum:numnum:numendlendl;coutcoutname:namename:nameendlendl;coutcoutsex:sexsex:sexendlendlendlendl;private:private:intint num;num;char name10;char name10;char sex;char sex;intint main()main()Student stud1(10010,Wang_li,f);Student stud1(10010,Wang_li,f);/建立建立对象象stud1stud1stud1.display();/stud1.display();/输出出学学生生1 1的的数数据据 Student stud2(10011,Zhang_fun,m);Student stud2(10011,Zhang_fun,m);/定定义对象象stud2stud2stud2.display();/stud2.display();/输出出学学生生2 2的的数数据据return 0;return 0;Logo9.3 调用构造函数和析构函数的顺序调用构造函数和析构函数的顺序 在使用构造函数和析构函数时,需要特别注意对在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。它们的调用时间和调用顺序。在一般情况下,在一般情况下,调用析构函数的次序正好与调用调用析构函数的次序正好与调用构造函数的次序相反:构造函数的次序相反:最先被调用的构造函数,其最先被调用的构造函数,其对应的对应的(同一对象中的同一对象中的)析构函数最后被调用,而最后析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用被调用的构造函数,其对应的析构函数最先被调用。如图如图9.1示意。示意。Logo9.3 调用构造函数和析构函数的顺序调用构造函数和析构函数的顺序Logo9.4 对象数组对象数组 数组数组不仅可以由简单变量组成不仅可以由简单变量组成(例如整型数组的例如整型数组的每一个元素都是整型变量每一个元素都是整型变量),也可以由对象组成也可以由对象组成(对象对象数组的每一个元素都是同类的对象数组的每一个元素都是同类的对象)。在日常生活中,有许多实体的属性是共同的,只在日常生活中,有许多实体的属性是共同的,只是属性的具体内容不同。例如一个班有是属性的具体内容不同。例如一个班有50个学生,个学生,每个学生的属性包括姓名、性别、年龄、成绩等。如每个学生的属性包括姓名、性别、年龄、成绩等。如果为每一个学生建立一个对象,需要分别取果为每一个学生建立一个对象,需要分别取50个对个对象名。用程序处理很不方便。这时可以定义一个象名。用程序处理很不方便。这时可以定义一个“学学生类生类”对象数组,每一个数组元素是一个对象数组,每一个数组元素是一个“学生类学生类”对象。例如对象。例如 Student stud50;/假设已声明了假设已声明了Student类,定义类,定义stud数组,有数组,有50个元素个元素Logo9.4 对象数组对象数组 建立数组时,同样要调用构造函数从而实现建立数组时,同样要调用构造函数从而实现对象对象数组元素的初始化。数组元素的初始化。如何使用如何使用构构造函造函数数完成完成对象象数数组元素的初始化?元素的初始化?构构造函造函数数只有一只有一个参数个参数构构造函造函数数有多有多个参数个参数Logo9.4 对象数组对象数组class Student public:Student(int n)num=n;private:int num;Student stu3=101,102,103;构构造函造函数数StudentStudent只有一只有一个参数个参数构构造函造函数数只有一只有一个参数个参数时如何初始化如何初始化对象象数数组元素元素值?Logo9.4 对象数组对象数组class Student public:Student(int n,string xm,char s)num=n;name=xm;sex=s;private:int num;string name;char sex;Student stu3=Student(101,”Zhang”,”nv”),Student(102,”Li”,”nan”),Student(101,”He”,”nv”);构构造函造函数数有多有多个参数个参数时如何初始化如何初始化对象象数数组元素元素值?构构造函造函数数StudentStudent有多有多个个参数参数Logo9.4 对象数组对象数组 在建立对象数组时,分别调用构造在建立对象数组时,分别调用构造函数,函数,对每个元素初始化对每个元素初始化。每一个元素每一个元素的实参分别用括号包起来的实参分别用括号包起来,对应构造函,对应构造函数的一组形参,不会混淆。数的一组形参,不会混淆。例例9.6 对象数组的使用方法。对象数组的使用方法。Logo1.1.#include include 2.2.using namespace std;using namespace std;3.3.classclass BoxBox4.4.public:public:5.5.BoxBox(int(int h=10,int w=12,int h=10,int w=12,int lenlen=15):=15):height(h),width(w),length(lenheight(h),width(w),length(len)/声明有默认参数的构造函数,用参数初始化表对数据成员声明有默认参数的构造函数,用参数初始化表对数据成员初始化初始化6.6.intint volume();volume();7.7.private:private:8.8.intint height;height;9.9.intint width;width;10.10.intint length;length;11.11.;12.12.intint BoxvolumeBoxvolume()()13.13.return(heightreturn(height*width*length);*width*length);14.14.Logo15.15.intint main()main()16.16.BoxBox a3=a3=17.17.Box Box(10,12,15),Box(15,18,20),Box(16,20,26)(10,12,15),Box(15,18,20),Box(16,20,26);/调用用构构造函造函数数BoxBox共共3 3次,提供次,提供3 3个个元素的元素的实参参18.18.coutcoutvolume of a0 is volume of a0 is a0.a0.volume()volume()endlendl;/调用用a0a0的的volumevolume函函数数19.19.coutcoutvolume of a1 is volume of a1 is a1.a1.volume()volume()endlendl;/调用用a1 a1 的的volumevolume函函数数20.20.coutcoutvolume of a2 is volume of a2 is a2.a2.volume()volume()endlendl;/调用用a2 a2 的的volumevolume函函数数21.21.return 0;return 0;22.22.Logo9.5 9.5 对象指针对象指针9.5.1 指向对象的指针指向对象的指针 在建立对象时,编译系统会为每一个对象分配一定的存储在建立对象时,编译系统会为每一个对象分配一定的存储空间,以存放其成员。对象空间的起始地址就是对象的指针。空间,以存放其成员。对象空间的起始地址就是对象的指针。可以定义一个指针变量,用来存放对象的指针。可以定义一个指针变量,用来存放对象的指针。定义指向类对象的指针变量的一般形式为定义指向类对象的指针变量的一般形式为 类名类名*对象指针变量名;对象指针变量名;如果有一个类:如果有一个类:class Timepublic:int hour;int minute;int sec;void get_time();void Time get_time()couthour:minute:sechourpt-hour pt pt所指向的对象中的所指向的对象中的hourhour成员,即成员,即t1.hourt1.hour(*(*pt).get_timept).get_time()()调用调用ptpt所指向的对象中的所指向的对象中的get_timeget_time函数,函数,t1.get_timet1.get_timept-pt-get_timeget_time()()Logo9.5.2 指向对象成员的指针指向对象成员的指针 对象有地址,存放对象初始地址的指针变对象有地址,存放对象初始地址的指针变量就是指向对象的指针变量。对象中的成员也量就是指向对象的指针变量。对象中的成员也有地址,存放对象成员地址的指针变量就是指有地址,存放对象成员地址的指针变量就是指向对象成员的指针变量。向对象成员的指针变量。1.指向对象数据成员的指针指向对象数据成员的指针定义指向对象数据成员的指针变量的方法和定义定义指向对象数据成员的指针变量的方法和定义指向普通变量的指针变量方法相同。例如指向普通变量的指针变量方法相同。例如定义指向对象数据成员的指针变量的一般形式为定义指向对象数据成员的指针变量的一般形式为 数据类型名数据类型名*指针变量名指针变量名;intint*p1;/*p1;/定定义指向整型指向整型数数据的指据的指针变量量Logo9.5.2 指向对象成员的指针指向对象成员的指针 如果如果Time类的数据成员类的数据成员hour为公用的整型数据,为公用的整型数据,则可以在类外通过指向对象数据成员的指针变量访问则可以在类外通过指向对象数据成员的指针变量访问对象数据成员对象数据成员hour。int*p1;p1=&t1.hour;/将对象将对象t1的数据成员的数据成员hour的地址赋给的地址赋给p1,p1指向指向t1.hourcout*p1endl;/输出输出t1.hour的值的值Logo9.5.2 指向对象成员的指针指向对象成员的指针2.指向对象成员函数的指针指向对象成员函数的指针定义指向公用成员函数的指针变量的一般形式为定义指向公用成员函数的指针变量的一般形式为 数据类型名数据类型名(类名类名*指针变量名指针变量名)(参数表列参数表列);void(Time*p2)();/定义定义p2为指向为指向Time类中公用成员函数的指针变量类中公用成员函数的指针变量使指针变量指向一个公用成员函数的一般形式为使指针变量指向一个公用成员函数的一般形式为 指针变量名指针变量名=&类名类名 成员函数名成员函数名;p2=&Time get_time;例例9.7 有关对象指针的使用方法。有关对象指针的使用方法。Logo1.1.#include include 2.2.using namespace std;using namespace std;3.3.classclass TimeTime4.4.public:public:5.5.TimeTime(int,int,int(int,int,int););6.6.intint hour;hour;7.7.intint minute;minute;8.8.intint sec;sec;9.9.void void get_timeget_time();();/声明公有成员函数声明公有成员函数10.10.;11.11.TimeTime TimeTime(int(int h,inth,int m,intm,int s)s)12.12.hour=h;hour=h;13.13.minute=m;minute=m;14.14.sec=s;sec=s;15.15.16.16.void void Timeget_timeTimeget_time()()/定定义公有成公有成员函函数数17.17.coutcouthour:minute:sechour:minute:secendlendl;Logo18.18.intint main()main()19.19.TimeTime t1t1(10,13,56);(10,13,56);/定定义TimeTime类对象象t1t120.20.intint*p1p1=&=&t1t1.hourhour;/定定义指向整型指向整型数数据的指据的指针变量量p1p1,并并使使p1p1指指t1.hourt1.hour21.21.coutcout*p1p1p2-get_timeget_time();();/调用用p2p2所指向所指向对象象(即即t1)t1)的的get_timeget_time函函数数25.25.void(void(TimeTime*p3p3)();)();/定定义指向指向TimeTime类公用成公用成员函函数数的指的指针变量量p3p326.26.p3p3=&=&Timeget_timeTimeget_time;/使使p3p3指向指向TimeTime类公用成公用成员函函数数get_timeget_time27.27.(t1.*p3)();(t1.*p3)();/调用用对象象t1t1中中p3p3所指的成所指的成员函函数数(即即t1.get_time(t1.get_time()28.28.Logo9.5.3 this 指针指针 C+规定,规定,this指针指针是隐含在对象成员函数内的一种特殊是隐含在对象成员函数内的一种特殊指针。指针。当一个对象被创建后,它的每一个成员函数都含有一个系当一个对象被创建后,它的每一个成员函数都含有一个系统统自动生成自动生成的隐含指针的隐含指针this,用以保存这个对象的地址。,用以保存这个对象的地址。这这个指针的名字是固定的,称为个指针的名字是固定的,称为this,因此因此this也称为也称为“指向本指向本对象的指针对象的指针”,它存取类成员变量的格式为:,它存取类成员变量的格式为:this-当对象调用成员函数时,自动将对象自身的地址当对象调用成员函数时,自动将对象自身的地址(指针指针),传递给成员函数,在成员函数中可直接使用该指针。传递给成员函数,在成员函数中可直接使用该指针。Logo#include include using namespace std;using namespace std;classclass SampleSample intint x,y;x,y;public:public:Sample Sample(intint a=0,a=0,intint b=0)b=0)x=a;y=b;x=a;y=b;void Print()void Print()coutcout x x endlendl;coutcout y y endlendl;void main()void main()Sample c2(3,5);Sample c2(3,5);c2.Print();c2.Print();成成员员函函数数中中隐隐含含着着一一个个指指针针this,它它指指向向调调用用成成员员函函数的对象,数的对象,如下述程序与上述程序等价:如下述程序与上述程序等价:Logo#include#include class Sampleclass Sample intint x,y;x,y;public:public:Sample(Sample(intint a=0,a=0,intint b=0)b=0)this-this-x=a;x=a;/在此例中在此例中this=&c2this=&c2。this-this-y=b;y=b;void Print()void Print()coutcout (this-x)x)endlendl;/在此例中在此例中this=&c2this=&c2。coutcout (this-y)y)endlendl;void main()void main()Sample c2(3,5);Sample c2(3,5);c2.Print();c2.Print();Logo9.5.3 this 指针指针 显式地使用显式地使用this指针修改以下程序(不改变程序指针修改以下程序(不改变程序运行结果)。运行结果)。计算柱体的体积程序。计算柱体的体积程序。Logo#include#include using namespace std;using namespace std;class Boxclass Boxpublic:public:Box(int,int,intBox(int,int,int);/);/声声明明带参数参数的的构构造函造函数数intint volume();/volume();/声声明明计算体算体积的函的函数数 private:private:intint height;height;intint width;width;intint length;length;Box:Box(intBox:Box(int h,inth,int w,intw,int lenlen)height=h;height=h;width=w;width=w;length=length=lenlen;intint Box:volumeBox:volume()()return(heightreturn(height*width*length);*width*length);intint main()main()Box box1(12,25,30);/Box box1(12,25,30);/建立建立对象象box1box1,并并指定指定box1box1长、宽、高的、高的值coutcoutThe volume of box1 isbox1.volume()The volume of box1 isbox1.volume()endlendl;Box box2(15,30,21);/Box box2(15,30,21);/建立建立对象象box2box2,并并指定指定box2box2长、宽、高的、高的值coutcoutThe volume of box2 isbox2.volume()The volume of box2 isbox2.volume()endlendl;return 0;return 0;Logo9.5.3 this 指针指针为什什么么使用使用thisthis指指针?thisthis指指针是是C+C+实现封装的一封装的一种种机制,机制,它将它将对象和象和该对象象调用的成用的成员函函数数连接在一起,在外接在一起,在外部看部看来来,每一,每一个个对象都象都拥有自己的函有自己的函数数成成员。thisthis指指针永永远指向指向当当前前对象。象。thisthisthisthisthisthisLogo9.6 共用数据的保护共用数据的保护 C+虽然采取了不少有效的措施虽然采取了不少有效的措施(如设如设private保护保护)以增加数据的安全性,但是有些数据以增加数据的安全性,但是有些数据却往往是共享的,人们可以在不同的场合通过不同却往往是共享的,人们可以在不同的场合通过不同的途径访问同一个数据对象。有时在无意之中的误的途径访问同一个数据对象。有时在无意之中的误操作会改变有关数据的状况,而这是人们所不希望操作会改变有关数据的状况,而这是人们所不希望出现的。出现的。既要使数据能在一定范围内共享,又要保证它不被任既要使数据能在一定范围内共享,又要保证它不被任意修改,这时可以使用意修改,这时可以使用constconst,即把有关的数据定义即把有关的数据定义为常量。为常量。Logo9.6 共用数据的保护共用数据的保护可以定义为可以定义为const的有:的有:对象对象常对象常对象对象成员对象成员常对象成员常对象成员指针指针常指针常指针引用引用常引用常引用常数据成员常数据成员常成员函数常成员函数Logo9.6.1 常对象常对象定义常对象的一般形式为定义常对象的一般形式为 类名类名 const 对象名对象名(实参表列实参表列);也可以把也可以把const写在最左面:写在最左面:const 类名类名 对象名对象名(实参表列实参表列);Time const t1(12,34,46);/t1是常对象是常对象 这样,在所有的场合中,保证对象这样,在所有的场合中,保证对象t1t1中的所有成员的值都中的所有成员的值都不能被修改。不能被修改。Logo9.6.1 常对象常对象 如果一个对象被声明为常对象,则不能调用该对象的非如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数型的成员函数(除了由系统自动调用的隐式的构造函数除了由系统自动调用的隐式的构造函数和析构函数和析构函数)。例如,对于例。例如,对
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!