第9章类和对象课件.ppt

上传人(卖家):晟晟文业 文档编号:3859110 上传时间:2022-10-19 格式:PPT 页数:118 大小:379.37KB
下载 相关 举报
第9章类和对象课件.ppt_第1页
第1页 / 共118页
第9章类和对象课件.ppt_第2页
第2页 / 共118页
第9章类和对象课件.ppt_第3页
第3页 / 共118页
第9章类和对象课件.ppt_第4页
第4页 / 共118页
第9章类和对象课件.ppt_第5页
第5页 / 共118页
点击查看更多>>
资源描述

1、第第9 9章章 关于类和对象的进一步讨论关于类和对象的进一步讨论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 类模板类模板2022-10-4 如果一个类中所有的成员都是如果一个类中所有的成员都是公用公用的,则可以在定义

2、对象时的,则可以在定义对象时对数据成员进行初始化。如对数据成员进行初始化。如class Timepublic:/声明为公用成员声明为公用成员 int hour;int minute;int sec;Time t1=14,56,30;/将将t1初始化为初始化为14:56:309.1 9.1 构造函数构造函数 9.1.1 9.1.1 对象的初始化对象的初始化2022-10-4注意:注意:类的数据成员是不能在声明类时初始化的。类的数据成员是不能在声明类时初始化的。如果数据成员是私有的,或者类中有如果数据成员是私有的,或者类中有privateprivate或或protectedprotected的成员

3、,就不能在定义对象时对数据成的成员,就不能在定义对象时对数据成员进行初始化。员进行初始化。class Timepublic:/声明为公用成员声明为公用成员 int hour=0;int minute=0;int sec=0;()()private:Time t1=14,56,30;2022-10-4构造函数是一种特殊的成员函数,在建立对象时构造函数是一种特殊的成员函数,在建立对象时自动执行。自动执行。构造函数的名字必须与类名同名构造函数的名字必须与类名同名构造函数不具有任何类型构造函数不具有任何类型无返回值无返回值构造函数的功能由用户定义,用户根据初始化的构造函数的功能由用户定义,用户根据初始

4、化的要求设计函数体和函数参数。要求设计函数体和函数参数。9.1.2 9.1.2 构造函数的作用构造函数的作用2022-10-4例例9.1 在例在例8.3基础上定义构造成员函数。基础上定义构造成员函数。#include using namespace std;class Timepublic:Time()hour=0;minute=0;sec=0;/构造函数不具有任何类型,无返回值构造函数不具有任何类型,无返回值void set_time();/函数声明函数声明void show_time();/函数声明函数声明private:int hour;int minute;int sec;/私有数据成

5、员私有数据成员;函数名与类名相同函数名与类名相同给数据成员赋初值给数据成员赋初值2022-10-4void Time set_time()cinhour;cinminute;cinsec;void Time show_time()couthour:minute:secendl;int main()Time t1;/建立对象建立对象t1,同时调用构造函数,同时调用构造函数t1.Time()t1.set_time();t1.show_time();Time t2;/建立对象建立对象t2,同时调用构造函数,同时调用构造函数t2.Time()t2.show_time();/显示显示t2的数据成员的值的

6、数据成员的值return 0;运行结果:运行结果:12 30 512:30:50:0:02022-10-4构造函数也可以在类内对构造函数进行声明而在类外构造函数也可以在类内对构造函数进行声明而在类外定义构造函数。将上例改为:定义构造函数。将上例改为:Time();/在类内对构造函数进行声明在类内对构造函数进行声明在类外定义构造函数:在类外定义构造函数:Time Time()/在类外要加上类名和域限定符在类外要加上类名和域限定符“”“”hour=0;minute=0;sec=0;2022-10-4说明:说明:(1)(1)在类对象进入其作用域时在类对象进入其作用域时调用调用构造函数。构造函数。(2

7、)(2)构造函数构造函数没有返回值没有返回值,因此也不需要在定义构,因此也不需要在定义构造函数时声明类型。造函数时声明类型。(3)(3)构造函数不需用户调用,也不能被用户调用。构造函数不需用户调用,也不能被用户调用。(4)(4)在构造函数的函数体中不仅可以对数据成员赋在构造函数的函数体中不仅可以对数据成员赋初值,而且可以包含其他语句。初值,而且可以包含其他语句。(5)(5)如果用户自己没有定义构造函数,则如果用户自己没有定义构造函数,则C+C+系统系统会会自动生成自动生成一个构造函数,只是这个构造函数的函一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作。数体是空的,也

8、没有参数,不执行初始化操作。2022-10-4构造函数首部的一般格式为构造函数首部的一般格式为:构造函数名构造函数名(类型类型 1 1 形参形参1 1,类型,类型2 2 形参形参2 2,)说明:说明:用户是不能调用构造函数的,因此无法采用户是不能调用构造函数的,因此无法采用常规的调用函数的方法给出实参。实参是在定义用常规的调用函数的方法给出实参。实参是在定义对象时给出的。定义对象的一般格式为对象时给出的。定义对象的一般格式为:类名类名 对象名对象名(实参实参1 1,实参,实参2 2,););9.1.3 9.1.3 带参数的构造函数带参数的构造函数2022-10-4例例9.2 9.2 有两个长方

9、柱,其长、宽、高分别为:有两个长方柱,其长、宽、高分别为:(1)12,20,25(1)12,20,25;(2)10,14,20(2)10,14,20。求它们的体积。求它们的体积。#include using namespace std;class Boxpublic:Box(int,int,int);/声明带参数的构造函数声明带参数的构造函数int volume();/声明计算体积的函数声明计算体积的函数 private:int height;int width;int length;BoxBox(int h,int w,int len)BoxBox(int h,int w,int len)/

10、在类外定义带参数的构造函数在类外定义带参数的构造函数height=h;height=h;width=w;width=w;length=len;length=len;2022-10-4int Box volume()/定义计算体积的函数定义计算体积的函数 return(height*width*length);int main()Box box1(12,25,30);cout“The volume of box1 is“box1.volume()endl;Box box2(15,30,21);cout“The volume of box2 is“box2.volume()endl;return

11、0;程序运行结果如下:程序运行结果如下:The volume of box1 is 9000The volume of box2 is 9450结论:(1)带参数的构造函数中的形参,其对应的实参在定义对象时给定。(2)用这种方法可以方便地实现对不同的对象进行不同的初始化。2022-10-4在函数首部实现对数据成员的初始化。例如例在函数首部实现对数据成员的初始化。例如例9.29.2中定义构中定义构造函数可以改用以下形式:造函数可以改用以下形式:Box Box(int h,int w,int len):height(h),width(w),length(len)优点:优点:写法方便、简练,尤其当需

12、要初始化的数据成员较写法方便、简练,尤其当需要初始化的数据成员较多时更显其优越性。甚至可以直接在类体中多时更显其优越性。甚至可以直接在类体中(而不是在类外而不是在类外)定义构造函数。定义构造函数。9.1.4 9.1.4 用参数初始化表对数据成员初始化用参数初始化表对数据成员初始化2022-10-4 在一个类中可以定义多个构造函数,以便对类在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法,供用户选用。对象提供不同的初始化的方法,供用户选用。构造函数的重载的特点:构造函数的重载的特点:这些构造函数具有相同的名字这些构造函数具有相同的名字而参数的个数或参数的类型不相同而参数的个数或

13、参数的类型不相同9.1.5 9.1.5 构造函数的重载构造函数的重载2022-10-4#include using namespace std;class Boxpublic:Box();Box(int h,int w,int len):height(h),width(w),length(len)int volume();private:int height,width,length;Box Box()/定义一个无参的构造函数定义一个无参的构造函数height=10;width=10;length=10;例9.3 定义两个构造函数,其中一个无参,一个有参数。2022-10-4int Box v

14、olume()return(height*width*length);int main()Box box1;/建立对象建立对象box1,不指定实参不指定实参cout“The volume of box1 is“box1.volume()endl;Box box2(15,30,25);/建立对象建立对象box2,指定指定3个实参个实参cout“The volume of box2 is“box2.volume()endl;return 0;2022-10-4说明:说明:(1)(1)调用构造函数时不必给出实参的构造函数,称调用构造函数时不必给出实参的构造函数,称为默认构造函数为默认构造函数(def

15、ault constructor)(default constructor)。一个类一个类只能有一个默认构造函数。只能有一个默认构造函数。(2)(2)如果在建立对象时选用的是无参构造函数,应如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。注意正确书写定义对象的语句。(3)(3)尽管在一个类中可以包含多个构造函数,但是尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。构造函数,并非每个构造函数都被执行。例如:例如:Box box1;Box box1();2022-

16、10-4构造函数中参数的值既可以通过实参传递,也可以构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。译系统就使形参取默认值。例例9.4 9.4 将上例中的构造函数改用含默认值的参数,将上例中的构造函数改用含默认值的参数,长、宽、高的默认值均为长、宽、高的默认值均为1010。改写如下:改写如下:9.1.6 9.1.6 使用默认参数的构造函数使用默认参数的构造函数2022-10-4#include using namespace std;class Boxpublic:Box(int h=1

17、0,int w=10,int len=10);/在声明构造函数时指定默认参数在声明构造函数时指定默认参数int volume();private:int height;int width;int length;Box Box(int h,int w,int len)/在定义函数时可以不指定默认参数在定义函数时可以不指定默认参数height=h;width=w;length=len;或或:Box Box(int h,int w,int len):height(h),width(w),length(len)默认参数在声明构造函数是给出默认参数在声明构造函数是给出2022-10-4int Box v

18、olume()return(height*width*length);int main()Box box1;/没有给实参没有给实参 coutThe volume of box1 is box1.volume()endl;Box box2(15);/只给定一个实参只给定一个实参coutThe volume of box2 is box2.volume()endl;Box box3(15,30);/只给定只给定2个实参个实参coutThe volume of box3 is box3.volume()endl;Box box4(15,30,20);/给定给定3个实参个实参coutThe volum

19、e of box4 is box4.volume()endl;return 0;2022-10-4程序运行结果为程序运行结果为:The volume of box1 is 1000The volume of box2 is 1500The volume of box3 is 4500The volume of box4 is 9000优点:优点:在构造函数中使用默认参数是方便而有效的,在构造函数中使用默认参数是方便而有效的,它提供了建立对象时的多种选择,它的作用相当于好它提供了建立对象时的多种选择,它的作用相当于好几个重载的构造函数。即使在调用构造函数时没有提几个重载的构造函数。即使在调用构造

20、函数时没有提供实参值,不仅不会出错,而且还确保按照默认的参供实参值,不仅不会出错,而且还确保按照默认的参数值对对象进行初始化。数值对对象进行初始化。2022-10-4说明:说明:(1)(1)应该在声明构造函数时指定默认值,而不能只在应该在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。定义构造函数时指定默认值。(2)(2)程序第程序第5 5行在声明构造函数时,形参名可以省略。行在声明构造函数时,形参名可以省略。(3)(3)如果构造函数的全部参数都指定了默认值,则在如果构造函数的全部参数都指定了默认值,则在定义对象时可以给一个或几个实参,也可以不给出实定义对象时可以给一个或几个实参

21、,也可以不给出实参。参。(4)(4)在一个类中定义了全部是默认参数的构造函数后,在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数。不能再定义重载构造函数。例如例如(4):Box(int=10,int=10,int=10);Box();Box(int,int);定义对象:定义对象:Box box1;/歧义性歧义性 Box box2(15,30);/歧义性歧义性例如例如(2):Box(int=10,int=10,int=10);例如例如(3):Box();Box(int=10,int=10,int=10);定义对象:定义对象:Box box1;/歧义性歧义性2022-10-4析构

22、函数析构函数(destructor)也是一个特殊的成员函数,也是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面它的作用与构造函数相反,它的名字是类名的前面加一个加一个“”符号。析构函数是与构造函数作用相符号。析构函数是与构造函数作用相反的函数。反的函数。当对象的生命期结束时,会自动执行析构函数。具当对象的生命期结束时,会自动执行析构函数。具体地说如果出现以下几种情况,程序就会执行析构体地说如果出现以下几种情况,程序就会执行析构函数:函数:如果在一个函数中定义了一个对象如果在一个函数中定义了一个对象(它是自动局它是自动局部对象部对象),当这个函数被调用结束时,对象应该释,当这个

23、函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。放,在对象释放前自动执行析构函数。9.2 9.2 析构函数析构函数2022-10-4static局部对象在函数调用结束时对象并不释放,局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在因此也不调用析构函数,只在main函数结束或调函数结束或调用用exit函数结束程序时,才调用函数结束程序时,才调用static局部对象的析局部对象的析构函数。构函数。如果定义了一个全局对象,则在程序的流程离开如果定义了一个全局对象,则在程序的流程离开其作用域时其作用域时(如如main函数结束或调用函数结束或调用exit函数函数)时,时,调

24、用该全局对象的析构函数。调用该全局对象的析构函数。如果用如果用new运算符动态地建立了一个对象,当用运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构运算符释放该对象时,先调用该对象的析构函数。函数。析构函数的作用析构函数的作用并不是删除对象,而是在撤销对象并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。占用的内存之前完成一些清理工作。2022-10-4析构函数没有函数类型,不返回任何值析构函数没有函数类型,不返回任何值析构函数没有参数析构函数没有参数,因此它不能被重载。因此它不能被重载。一个类可以有多个构造函数,但只能有一个析构一个类可以有多个构

25、造函数,但只能有一个析构函数。函数。如果用户没有定义析构函数,如果用户没有定义析构函数,C+C+编译系统会自编译系统会自动生成一个析构函数,但它只是徒有析构函数的名动生成一个析构函数,但它只是徒有析构函数的名称和形式,实际上什么操作都不进行。称和形式,实际上什么操作都不进行。2022-10-4例例9.5 包含构造函数和析构函数的包含构造函数和析构函数的C+程序。程序。#include#includeusing namespace std;class Student /声明声明Student类类public:Student(int n,string nam,char s)/定义构造函数定义构造函

26、数num=n;name=nam;sex=s;coutConstructor called.endl;Student()/定义析构函数定义析构函数coutDestructor called.endl;void display()/定义成员函数定义成员函数coutnum:numendl;coutname:nameendl;coutsex:sexendlendl;private:int num;char name10;char sex;2022-10-4int main()Student stud1(10010,Wang_li,f);/建立对象建立对象stud1stud1.display();/输出

27、学生输出学生1的数据的数据 Student stud2(10011,Zhang_fun,m);/定义对象定义对象stud2stud2.display();/输出学生输出学生2的数据的数据return 0;2022-10-4程序运行结果如下:程序运行结果如下:Constructor called.(执行执行stud1的构造函数的构造函数)num:10010 (执行执行stud1的的display函数函数)name:Wang_lisex:fConstructor called.(执行执行stud2的构造函数的构造函数)num:10011 (执行执行stud2的的display函数函数)name:Z

28、hang_funsex:mDestructor called.(执行执行stud2的析构函数的析构函数)Destructor called.(执行执行stud1的析构函数的析构函数)2022-10-4调用析构函数的次序正好与调用构造函数的次序相反。如图9.1示意。9.3 调用构造函数和析构函数的顺序图9.12022-10-4什么时候调用构造函数和析构函数:什么时候调用构造函数和析构函数:(1)在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在文件中的所有函数(包括main函数)执行之前调用。但如果一个程序中有多个文件,而不同的文件中都定义了全局对象,则这些对象的构造函数的执行

29、顺序是不确定的。当main函数执行完毕或调用exit函数时(此时程序终止),调用析构函数。2022-10-4(2)如果定义的是局部自动对象(例如在函数中定义对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。(3)如果在函数中定义静态(static)局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。2022-10-4对象数组对象数组:数组由对象组成数组由对象组成(对象数组的每一个元素对

30、象数组的每一个元素都是同类的对象都是同类的对象)。例如例如 Student stud50;/假设已声明了假设已声明了Student类,定义类,定义stud数组,有数组,有50个元素个元素9.4 对象数组2022-10-4在建立数组时,如果有N个元素,需要调用N次构造函数。如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供实参。如:Student stud3=60,70,78;/合法,3个实参分别传递给3个数组元素的构造函数如果构造函数有多个参数,很容易造成实参与形参的对应关系不清晰,出现歧义性。例如,类例如,类StudentStudent的构造函数有多个参数,且为默认参数:

31、的构造函数有多个参数,且为默认参数:Student Student(int=1001,int=18,int=60);Student Student(int=1001,int=18,int=60);如果定义对象数组的语句为如果定义对象数组的语句为:Student stud3=1005,60,70;Student stud3=1005,60,70;编译系统只为每个对象元素的构造函数传递一个实参,编译系统只为每个对象元素的构造函数传递一个实参,2022-10-4在定义数组时提供的实参个数不能超过数组元素个数,如:Student stud3=60,70,78,45;/不合法构造函数有多个参数,在定义对

32、象数组时初始化:如果构造函数有3个参数,分别代表学号、年龄、成绩。则可以这样定义对象数组:Student Stud3=Student(1001,18,87),Student(1002,19,76),Student(1003,18,72);2022-10-4例例9.6 9.6 对象数组的使用方法。对象数组的使用方法。#include using namespace std;class Boxpublic:Box(int h=10,int w=12,int len=15):height(h),width(w),length(len)int volume();private:int height,w

33、idth,length;2022-10-4int Box volume()return(height*width*length);int main()Box a3=Box(10,12,15),Box(15,18,20),Box(16,20,26);coutvolume of a0 is a0.volume()endl;coutvolume of a1 is a1.volume()endl;coutvolume of a2 is a2.volume()endl;运行结果如下:运行结果如下:volume of a0 is 1800volume of a1 is 5400volume of a2 i

34、s 83202022-10-4在建立对象时,可以定义一个指针变量,用来存放在建立对象时,可以定义一个指针变量,用来存放对象的指针。定义指向类对象的指针变量的一般形对象的指针。定义指向类对象的指针变量的一般形式为式为:类名类名 *对象指针名;对象指针名;如果有一个类:如果有一个类:class Timeclass Timepublic:public:int hour,minute,sec;int hour,minute,sec;void get_time();void get_time();9.5 9.5 对象指针对象指针 9.5.1 9.5.1 指向对象的指针指向对象的指针2022-10-4vo

35、id Time get_time()couthour:minute:sechour /pt pt所指向的对象中的所指向的对象中的hour成员,即成员,即t1.hour(*pt).get_time()/调用调用pt所指向的对象中的所指向的对象中的get_time函数函数pt-get_time()/调用调用pt所指向的对象中的所指向的对象中的get_time函数函数2022-10-4对象有地址,存放对象初始地址的指针变量就是指对象有地址,存放对象初始地址的指针变量就是指向对象的指针变量。对象中的成员也有地址,存放向对象的指针变量。对象中的成员也有地址,存放对象成员地址的指针变量就是指向对象成员的指

36、针对象成员地址的指针变量就是指向对象成员的指针变量。变量。9.5.2 9.5.2 指向对象成员的指针指向对象成员的指针2022-10-41.1.指向对象数据成员的指针指向对象数据成员的指针定义指向对象数据成员的指针变量的一般形式为定义指向对象数据成员的指针变量的一般形式为:数据类型名数据类型名 *指针变量名;指针变量名;例如例如:如果如果TimeTime类的数据成员类的数据成员hourhour为公用的整型数为公用的整型数据,则可以在类外通过指向对象数据成员的指针变据,则可以在类外通过指向对象数据成员的指针变量访问对象数据成员量访问对象数据成员hourhour。int int*p1;p1;p1=

37、&t1.hour;p1=&t1.hour;cout cout*p1endl;p1endl;2022-10-42.2.指向对象成员函数的指针指向对象成员函数的指针定义指向公用成员函数的指针变量的一般形式为定义指向公用成员函数的指针变量的一般形式为 数据类型名数据类型名(类名类名*指针变量名指针变量名)()(参数表列参数表列);赋值语句中,指针变量的类型必须与赋值号右侧函数赋值语句中,指针变量的类型必须与赋值号右侧函数的类型相匹配,要求的类型相匹配,要求:函数参数的类型和参数个数;函数参数的类型和参数个数;函数返回值的类型;函数返回值的类型;所属的类。所属的类。定义指向成员函数的指针变量应该采用下

38、面的形式:定义指向成员函数的指针变量应该采用下面的形式:void(Timevoid(Time*p2)();p2)();2022-10-4指向公用成员函数的指针变量指向一个公用成员函指向公用成员函数的指针变量指向一个公用成员函数的入口地址如数的入口地址如:p2=&Timeget_time;p2=&Timeget_time;使指针变量指向一个公用成员函数的一般形式为使指针变量指向一个公用成员函数的一般形式为:指针变量名指针变量名=&=&类名类名成员函数名成员函数名;例例9.7 9.7 有关对象指针的使用方法有关对象指针的使用方法。#include#include using namespace s

39、td;using namespace std;class Timeclass Timepublic:public:Time(int,int,int);Time(int,int,int);int hour;int hour;int minute;int minute;int sec;int sec;void get_time();void get_time();/声明公有成员函数声明公有成员函数;2022-10-4TimeTime(int h,int m,int s)TimeTime(int h,int m,int s)hour=h;hour=h;minute=m;minute=m;sec=s;

40、sec=s;void Timeget_time()void Timeget_time()/定义公有成员函数定义公有成员函数couthour:minute:secendl;couthour:minute:secendl;int main()int main()Time t1(10,13,56);Time t1(10,13,56);int int*p1=&t1.hour;p1=&t1.hour;coutcout*p1endl;p1get_time();p2-get_time();void(Timevoid(Time*p3)();p3)();p3=&Timeget_time;p3=&Timeget_

41、time;(t1.(t1.*p3)();p3)();2022-10-4程序运行结果为程序运行结果为:10 10 10:13:5610:13:5610:13:5610:13:5610:13:5610:13:56说明:说明:(1)(1)成员函数的入口地址的正确写法是:成员函数的入口地址的正确写法是:(2)(2)&类名类名成员函数名成员函数名(2)main(2)main函数第函数第8 8、9 9两行可以合写为一行:两行可以合写为一行:void(Timevoid(Time*p3)()=&Timeget_time;p3)()=&Timeget_time;2022-10-4每个对象中的数据成员都分别占有存

42、储空间,但是,每个对象中的数据成员都分别占有存储空间,但是,不同对象都调用同一个函数代码段。不同对象都调用同一个函数代码段。在每一个成员函数中都包含一个特殊的指针,这个在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为指针的名字是固定的,称为thisthis。它是指向本类对它是指向本类对象的指针,象的指针,它的值是当前被调用的成员函数所在的它的值是当前被调用的成员函数所在的对象的起始地址。对象的起始地址。9.5.3 this 9.5.3 this 指针指针2022-10-4例如,当调用成员函数例如,当调用成员函数a.volumea.volume时,编译系统就把时,编译系统就把

43、对象对象a a的起始地址赋给的起始地址赋给thisthis指针,于是在成员函数引指针,于是在成员函数引用数据成员时,就按照用数据成员时,就按照thisthis的指向找到对象的指向找到对象a a的数据的数据成员。例如成员。例如volumevolume函数要计算函数要计算heightheight*widthwidth*lengthlength的值,实际上是执行:的值,实际上是执行:(this-height)(this-height)*(this-width)(this-width)*(this-length)(this-length)由于当前由于当前thisthis指向指向a a,因此相当于执行:

44、,因此相当于执行:(a.height)(a.height)*(a.width)(a.width)*(a.length)(a.length)这就计算出长方体这就计算出长方体a a的体积。的体积。2022-10-4thisthis指针是隐式使用的,它是作为参数被传递给成员函数指针是隐式使用的,它是作为参数被传递给成员函数的。本来,成员函数的。本来,成员函数volumevolume的定义如下:的定义如下:int Boxvolume()int Boxvolume()return(heightreturn(height*widthwidth*length);length);C+C+把它处理为把它处理为i

45、nt Boxvolume(Box int Boxvolume(Box*this)this)return(return(this-this-height height*this-this-width width*this-this-length);length);即在成员函数的形参表列中增加一个即在成员函数的形参表列中增加一个thisthis指针。在调用该指针。在调用该成员函数时,实际上是用以下方式调用的:成员函数时,实际上是用以下方式调用的:a.volume(a.volume(&a&a););将对象将对象a a的地址传给形参的地址传给形参thisthis指针。然后按指针。然后按thisthis

46、的指向去引的指向去引用其他成员。用其他成员。2022-10-4说明:说明:这些都是编译系统自动实现的,编程序者不必人为地在形参中这些都是编译系统自动实现的,编程序者不必人为地在形参中增加增加thisthis指针,也不必将对象指针,也不必将对象a a的地址传给的地址传给thisthis指针。指针。在需要时也可以显式地使用在需要时也可以显式地使用thisthis指针。下面两种表示方法都是指针。下面两种表示方法都是合法的、相互等价的。合法的、相互等价的。return(height return(height*width width*length);length);/隐含使用隐含使用thisthis指

47、针指针return(this-height return(this-height*this-width this-width*this-length);this-length);/显显式式2022-10-4C+C+虽然采取了不少有效的措施虽然采取了不少有效的措施(如设如设privateprivate保护保护)以增加数据的安全性,但是有些数据却往往是共享以增加数据的安全性,但是有些数据却往往是共享的,人们可以在不同的场合通过不同的途径访问同的,人们可以在不同的场合通过不同的途径访问同一个数据对象。有时在无意之中的误操作会改变有一个数据对象。有时在无意之中的误操作会改变有关数据的状况,而这是人们所

48、不希望出现的。关数据的状况,而这是人们所不希望出现的。既要使数据能在一定范围内共享,又要保证它不被既要使数据能在一定范围内共享,又要保证它不被任意修改,这时可以使用任意修改,这时可以使用constconst,即把有关的数据,即把有关的数据定义为常量。定义为常量。9.6 9.6 共用数据的保护共用数据的保护2022-10-4定义常对象的一般形式为:类名类名 const 对象名对象名(实参表列实参表列););也可以把const写在最左面:const 类名类名 对象名对象名(实参表列实参表列););在定义对象时指定对象为常对象。常对象必须要有初值。如:Time const t1(12,34,46);

49、/t1是常对象这样,在所有的场合中,对象t1中的所有成员的值都不能被修改。9.6.1 9.6.1 常对象常对象2022-10-4如果一个对象被声明为常对象,则不能调用该对象如果一个对象被声明为常对象,则不能调用该对象的非的非constconst型的成员函数型的成员函数(除了由系统自动调用的隐式除了由系统自动调用的隐式的构造函数和析构函数的构造函数和析构函数)。例如:const Time t1(10,15,36);/定义常对象定义常对象t1t1.get_time();/企图调用企图调用t1t1中的非中的非const型成员函数型成员函数这是为了防止这些函数会修改常对象中数据成员的值。对不安全的因素

50、予以拦截。引用常对象中的数据成员很简单,只需将该成员函数声明为const即可。2022-10-4如如void get_time()void get_time()constconst;/将函数声明为将函数声明为constconst 常成员函数可以访问常对象中的数据成员,但仍常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值。然不允许修改常对象中数据成员的值。例外:数据成员声明为例外:数据成员声明为mutablemutable,在常对象中可以,在常对象中可以修改该数据成员的值。修改该数据成员的值。如如 :mutablemutable int count;int count;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(第9章类和对象课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|