《第9章类和对象.ppt》由会员分享,可在线阅读,更多相关《第9章类和对象.ppt(118页珍藏版)》请在三一文库上搜索。
1、2019/4/7,1,第9章 关于类和对象的进一步讨论,9.1 构造函数 9.2 析构函数 9.3 调用构造函数和析构函数的顺序 9.4 对象数组 9.5 对象指针 9.6 共用数据的保护 9.7 对象的动态建立和释放 9.8 对象的赋值和复制 9.9 静态成员 9.10 友元 9.11 类模板,2019/4/7,2,如果一个类中所有的成员都是公用的,则可以在定义对象时对数据成员进行初始化。如 class Time public: /声明为公用成员 int hour; int minute; int sec; ; Time t1=14,56,30; /将t1初始化为14:56:30,9.1 构
2、造函数 9.1.1 对象的初始化,2019/4/7,3,注意: 类的数据成员是不能在声明类时初始化的。 如果数据成员是私有的,或者类中有private或protected的成员,就不能在定义对象时对数据成员进行初始化。,class Time public: /声明为公用成员 int hour=0; int minute=0; int sec=0; ;,(),private:,Time t1=14,56,30;,2019/4/7,4,构造函数是一种特殊的成员函数,在建立对象时自动执行。 构造函数的名字必须与类名同名 构造函数不具有任何类型 无返回值 构造函数的功能由用户定义,用户根据初始化的要求
3、设计函数体和函数参数。,9.1.2 构造函数的作用,2019/4/7,5,例9.1 在例8.3基础上定义构造成员函数。 #include using namespace std; class Time public: Time( ) hour=0; minute=0;sec=0; /构造函数不具有任何类型,无返回值 void set_time( ); /函数声明 void show_time( ); /函数声明 private: int hour; int minute; int sec; /私有数据成员 ;,函数名与类名相同,给数据成员赋初值,2019/4/7,6,void Timeset_
4、time( ) cinhour;cinminute;cinsec; void Timeshow_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的数据成员的值 return 0;,运行结果: 12 30 5 12:30:5 0:0:0,2019/4/7,7,构造函数也可以在类内对构造函数进行声明而在
5、类外定义构造函数。将上例改为: Time( ); /在类内对构造函数进行声明 在类外定义构造函数: TimeTime( ) / 在类外要加上类名和域限定符“” hour=0; minute=0; sec=0; ,2019/4/7,8,说明: (1) 在类对象进入其作用域时调用构造函数。 (2) 构造函数没有返回值,因此也不需要在定义构造函数时声明类型。 (3) 构造函数不需用户调用,也不能被用户调用。 (4) 在构造函数的函数体中不仅可以对数据成员赋初值,而且可以包含其他语句。 (5) 如果用户自己没有定义构造函数,则C+系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,
6、不执行初始化操作。,2019/4/7,9,构造函数首部的一般格式为: 构造函数名(类型 1 形参1,类型2 形参2,) 说明: 用户是不能调用构造函数的,因此无法采用常规的调用函数的方法给出实参。实参是在定义对象时给出的。定义对象的一般格式为: 类名 对象名(实参1,实参2,);,9.1.3 带参数的构造函数,2019/4/7,10,例9.2 有两个长方柱,其长、宽、高分别为: (1)12,20,25;(2)10,14,20。求它们的体积。#include using namespace std; class Box public: Box(int,int,int); /声明带参数的构造函数
7、int volume( ); /声明计算体积的函数 private: int height; int width; int length; ;,BoxBox(int h,int w,int len) /在类外定义带参数的构造函数 height=h; width=w; length=len;,2019/4/7,11,int Boxvolume( ) /定义计算体积的函数 return(height*width*length); int main( ) Box box1(12,25,30); cout“The volume of box1 is “box1.volume( )endl; Box b
8、ox2(15,30,21); cout“The volume of box2 is “box2.volume( )endl; return 0; 程序运行结果如下: The volume of box1 is 9000 The volume of box2 is 9450,结论: (1) 带参数的构造函数中的形参,其对应的实参在定义对象时给定。 (2) 用这种方法可以方便地实现对不同的对象进行不同的初始化。,2019/4/7,12,在函数首部实现对数据成员的初始化。例如例9.2中定义构造函数可以改用以下形式: BoxBox(int h,int w,int len): height(h),wid
9、th(w),length(len) 优点:写法方便、简练,尤其当需要初始化的数据成员较多时更显其优越性。甚至可以直接在类体中(而不是在类外)定义构造函数。,9.1.4 用参数初始化表对数据成员初始化,2019/4/7,13,在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化的方法,供用户选用。 构造函数的重载的特点: 这些构造函数具有相同的名字 而参数的个数或参数的类型不相同,9.1.5 构造函数的重载,2019/4/7,14,#include using namespace std; class Box public: Box( ); Box(int h,int w,int len
10、):height(h),width(w),length(len) int volume( ); private:int height, width, length; ; BoxBox( ) /定义一个无参的构造函数 height=10;width=10;length=10;,例9.3 定义两个构造函数,其中一个无参,一个有参数。,2019/4/7,15,int Boxvolume( ) return(height*width*length); int main( ) Box box1; /建立对象box1,不指定实参 cout“The volume of box1 is “box1.volum
11、e( )endl; Box box2(15,30,25); /建立对象box2,指定3个实参 cout“The volume of box2 is “box2.volume( )endl; return 0; ,2019/4/7,16,说明: (1) 调用构造函数时不必给出实参的构造函数,称为默认构造函数(default constructor)。一个类只能有一个默认构造函数。 (2) 如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。 (3) 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。,例如:Bo
12、x box1; Box box1(); ,2019/4/7,17,构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值。 例9.4 将上例中的构造函数改用含默认值的参数,长、宽、高的默认值均为10。 改写如下:,9.1.6 使用默认参数的构造函数,2019/4/7,18,#include using namespace std; class Box public: Box(int h=10,int w=10,int len=10); /在声明构造函数时指定默认参数 int volume( ); private: int height;
13、int width; int length; BoxBox(int h,int w,int len) /在定义函数时可以不指定默认参数 height=h; width=w; length=len; ,或: BoxBox(int h,int w,int len):height(h),width(w),length(len) ,默认参数在声明构造函数是给出,2019/4/7,19,int Boxvolume( ) return(height*width*length); int main( ) Box box1; /没有给实参 coutThe volume of box1 is box1.volu
14、me( )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 volume of box4 is box4.volume( )endl; return 0;,2019/4/7,20,程序运行结果为: The volume of box1 is 1000 The volume of bo
15、x2 is 1500 The volume of box3 is 4500 The volume of box4 is 9000 优点: 在构造函数中使用默认参数是方便而有效的,它提供了建立对象时的多种选择,它的作用相当于好几个重载的构造函数。即使在调用构造函数时没有提供实参值,不仅不会出错,而且还确保按照默认的参数值对对象进行初始化。,2019/4/7,21,说明: (1) 应该在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。 (2) 程序第5行在声明构造函数时,形参名可以省略。 (3) 如果构造函数的全部参数都指定了默认值,则在定义对象时可以给一个或几个实参,也可以不给出实
16、参。 (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; /歧义性,2019/4/7,22,析构函数(destructor)也是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一个“”
17、符号。析构函数是与构造函数作用相反的函数。 当对象的生命期结束时,会自动执行析构函数。具体地说如果出现以下几种情况,程序就会执行析构函数: 如果在一个函数中定义了一个对象(它是自动局部对象),当这个函数被调用结束时,对象应该释放,在对象释放前自动执行析构函数。,9.2 析构函数,2019/4/7,23,static局部对象在函数调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数。 如果定义了一个全局对象,则在程序的流程离开其作用域时(如main函数结束或调用exit函数) 时,调用该全局对象的析构函数。 如果用n
18、ew运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。 析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。,2019/4/7,24,析构函数没有函数类型,不返回任何值 析构函数没有参数,因此它不能被重载。 一个类可以有多个构造函数,但只能有一个析构函数。 如果用户没有定义析构函数,C+编译系统会自动生成一个析构函数,但它只是徒有析构函数的名称和形式,实际上什么操作都不进行。,2019/4/7,25,例9.5 包含构造函数和析构函数的C+程序。 #include #include using namespace std; class
19、 Student /声明Student类 public: Student(int n,string nam,char s ) /定义构造函数 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; ;,201
20、9/4/7,26,int main( ) Student stud1(10010,Wang_li,f); /建立对象stud1 stud1.display( ); /输出学生1的数据 Student stud2(10011,Zhang_fun,m); /定义对象stud2 stud2.display( ); /输出学生2的数据 return 0; ,2019/4/7,27,程序运行结果如下: Constructor called. (执行stud1的构造函数) num: 10010 (执行stud1的display函数) name:Wang_li sex: f Constructor call
21、ed. (执行stud2的构造函数) num: 10011 (执行stud2的display函数) name:Zhang_fun sex:m Destructor called. (执行stud2的析构函数) Destructor called. (执行stud1的析构函数),2019/4/7,28,调用析构函数的次序正好与调用构造函数的次序相反。如图9.1示意。,9.3 调用构造函数和析构函数的顺序,图9.1,2019/4/7,29,什么时候调用构造函数和析构函数: (1) 在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在文件中的所有函数(包括main函数)执行之前调用。
22、但如果一个程序中有多个文件,而不同的文件中都定义了全局对象,则这些对象的构造函数的执行顺序是不确定的。当main函数执行完毕或调用exit函数时(此时程序终止),调用析构函数。,2019/4/7,30,(2) 如果定义的是局部自动对象(例如在函数中定义对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。 (3) 如果在函数中定义静态(static)局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调
23、用析构函数。,2019/4/7,31,对象数组:数组由对象组成(对象数组的每一个元素都是同类的对象)。 例如 Student stud50; /假设已声明了Student类,定义stud数组,有50个元素,9.4 对象数组,2019/4/7,32,在建立数组时,如果有N个元素,需要调用N次构造函数。 如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供实参。 如: Student stud3=60,70,78; /合法,3个实参分别传递给3个数组元素的构造函数 如果构造函数有多个参数,很容易造成实参与形参的对应关系不清晰,出现歧义性。,例如,类Student的构造函数有多个参
24、数,且为默认参数: Student Student(int=1001,int=18,int=60); 如果定义对象数组的语句为: Student stud3=1005,60,70; 编译系统只为每个对象元素的构造函数传递一个实参,,2019/4/7,33,在定义数组时提供的实参个数不能超过数组元素个数,如: Student stud3=60,70,78,45; /不合法 构造函数有多个参数,在定义对象数组时初始化: 如果构造函数有3个参数,分别代表学号、年龄、成绩。则可以这样定义对象数组: Student Stud3= Student(1001,18,87), Student(1002,19,
25、76), Student(1003,18,72) ;,2019/4/7,34,例9.6 对象数组的使用方法。 #include using namespace std; class Box public: Box(int h=10,int w=12,int len=15): height(h),width(w),length(len) int volume( ); private: int height, width, length; ;,2019/4/7,35,int Boxvolume( ) return(height*width*length); int main( ) Box a3=B
26、ox(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 1800 volume of a1 is 5400 volume of a2 is 8320,2019/4/7,36,在建立对象时,可以定义一个指针变量,用来存放对象的指针。定义指向类对象的指针变量的一般形式为 : 类名 *对象指针名
27、; 如果有一个类: class Time public: int hour, minute, sec; void get_time( ); ;,9.5 对象指针 9.5.1 指向对象的指针,2019/4/7,37,void Timeget_time( ) couthour / pt所指向的对象中的hour成员,即t1.hour (*pt).get_time ( ) /调用pt所指向的对象中的get_time函数 pt-get_time ( ) /调用pt所指向的对象中的get_time函数,2019/4/7,38,对象有地址,存放对象初始地址的指针变量就是指向对象的指针变量。对象中的成员也有地
28、址,存放对象成员地址的指针变量就是指向对象成员的指针变量。,9.5.2 指向对象成员的指针,2019/4/7,39,1. 指向对象数据成员的指针 定义指向对象数据成员的指针变量的一般形式为: 数据类型名 *指针变量名; 例如:如果Time类的数据成员hour为公用的整型数据,则可以在类外通过指向对象数据成员的指针变量访问对象数据成员hour。 int *p1; p1=,2019/4/7,40,2. 指向对象成员函数的指针 定义指向公用成员函数的指针变量的一般形式为 数据类型名 (类名*指针变量名)(参数表列); 赋值语句中,指针变量的类型必须与赋值号右侧函数的类型相匹配,要求: 函数参数的类型
29、和参数个数; 函数返回值的类型; 所属的类。 定义指向成员函数的指针变量应该采用下面的形式: void (Time*p2)( );,2019/4/7,41,指向公用成员函数的指针变量指向一个公用成员函数的入口地址如 : p2=,例9.7 有关对象指针的使用方法。 #include using namespace std; class Time public: Time(int ,int,int); int hour; int minute; int sec; void get_time( ); /声明公有成员函数 ;,2019/4/7,42,TimeTime(int h,int m,int s
30、) hour=h; minute=m; sec=s; void Timeget_time( ) /定义公有成员函数 couthour:minute: secendl;,int main( ) Time t1(10,13,56); int *p1= ,2019/4/7,43,程序运行结果为: 10 10:13:56 10:13:56 10:13:56 说明: 成员函数的入口地址的正确写法是: ,2019/4/7,44,每个对象中的数据成员都分别占有存储空间,但是,不同对象都调用同一个函数代码段。 在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为this。它是指向本类对象的指针
31、,它的值是当前被调用的成员函数所在的对象的起始地址。,9.5.3 this 指针,2019/4/7,45,例如,当调用成员函数a.volume时,编译系统就把对象a的起始地址赋给this指针,于是在成员函数引用数据成员时,就按照this的指向找到对象a的数据成员。例如volume函数要计算height*width*length的值,实际上是执行: (this-height)*(this-width)*(this-length) 由于当前this指向a,因此相当于执行: (a.height)*(a.width)*(a.length) 这就计算出长方体a的体积。,2019/4/7,46,this指
32、针是隐式使用的,它是作为参数被传递给成员函数的。本来,成员函数volume的定义如下: int Boxvolume( ) return (height*width*length); C+把它处理为 int Boxvolume(Box *this) return(this-height * this-width * this-length); 即在成员函数的形参表列中增加一个this指针。在调用该成员函数时,实际上是用以下方式调用的: a.volume( 将对象a的地址传给形参this指针。然后按this的指向去引用其他成员。,2019/4/7,47,说明: 这些都是编译系统自动实现的,编程序者
33、不必人为地在形参中增加this指针,也不必将对象a的地址传给this指针。 在需要时也可以显式地使用this指针。下面两种表示方法都是合法的、相互等价的。 return(height * width * length); /隐含使用this指针 return(this-height * this-width * this-length); /显式,2019/4/7,48,C+虽然采取了不少有效的措施(如设private保护)以增加数据的安全性,但是有些数据却往往是共享的,人们可以在不同的场合通过不同的途径访问同一个数据对象。有时在无意之中的误操作会改变有关数据的状况,而这是人们所不希望出现的。
34、 既要使数据能在一定范围内共享,又要保证它不被任意修改,这时可以使用const,即把有关的数据定义为常量。,9.6 共用数据的保护,2019/4/7,49,定义常对象的一般形式为: 类名 const 对象名(实参表列); 也可以把const写在最左面: const 类名 对象名(实参表列); 在定义对象时指定对象为常对象。常对象必须要有初值。如: Time const t1(12,34,46); /t1是常对象 这样,在所有的场合中,对象t1中的所有成员的值都不能被修改。,9.6.1 常对象,2019/4/7,50,如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数(除了由
35、系统自动调用的隐式的构造函数和析构函数)。 例如:const Time t1(10,15,36); /定义常对象t1 t1.get_time( ); /企图调用t1中的非const型成员函数 这是为了防止这些函数会修改常对象中数据成员的值。对不安全的因素予以拦截。 引用常对象中的数据成员很简单,只需将该成员函数声明为const即可。,2019/4/7,51,如void get_time( ) const; /将函数声明为const 常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值。 例外:数据成员声明为mutable,在常对象中可以修改该数据成员的值。 如 :muta
36、ble int count; 把count声明为可变的数据成员,这样就可以用声明为const的成员函数来修改它的值。,2019/4/7,52,可以将对象的成员声明为const,包括: 常数据成员 常成员函数。 1. 常数据成员 用关键字const来声明常数据成员。常数据成员的值是不能改变的。只能通过构造函数的参数初始化表对常数据成员进行初始化。,9.6.2 常对象成员,2019/4/7,53,如: const int hour; /声明hour为常数据成员 不能采用在构造函数中对常数据成员赋初值的方法。 TimeTime(int h) hour=h;/ 非法!不能赋值 在类外定义构造函数,应写
37、成以下形式: TimeTime(int h):hour(h) /用初始化表初始化 常对象的数据成员都是常数据成员,因此常对象的构造函数只能用参数初始化表对常数据成员进行初始化。,2019/4/7,54,2. 常成员函数 如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们,例如只用于输出数据等。如: void get_time( ) const; 注意: const的位置在函数名和括号之后,const是函数类型的一部分,在声明和定义函数时都要有const关键字,在调用时不必加const。 常成员函数可以引用 (非)const数据成员。 const数据成员可以被(非) co
38、nst成员函数引用。,2019/4/7,55,(1) 如果在一个类中,一些数据成员的值不允许改变,则这一部分数据成员声明为const,以保证其值不被改变,可以用非const的成员函数引用这些数据成员的值,并修改非const数据成员的值。 (2) 如果要求所有的数据成员的值都不允许改变,则可以将所有的数据成员声明为const,或将对象声明为const(常对象),然后用const成员函数引用数据成员,这样起到“双保险”的作用,切实保证了数据成员不被修改。,2019/4/7,56,(3) 如果已定义了一个常对象,只能调用其中的const成员函数,而不能调用非const成员函数(不论这些函数是否会修改
39、对象中的数据)。这是为了保证数据的安全。如果需要访问对象中的数据成员,可将常对象中所有成员函数都声明为const成员函数,但应确保在函数中不修改对象中的数据成员。 不要误认为常对象中的成员函数都是常成员函数。常对象只保证其数据成员是常数据成员,其值不被修改。如果在常对象中的成员函数未加const声明,编译系统把它作为非const成员函数处理。 注意: 常成员函数不能调用另一个非const成员函数。,2019/4/7,57,将指针变量声明为const型,这样指针值始终保持为其初值,不能改变。如 Time t1(10,12,15),t2; /定义对象 Time * const ptr1 = / 错
40、误,ptr1不能改变指向 定义指向对象的常指针的一般形式为: 类名 * const 指针变量名=对象地址; 注意:在定义指针变量时使之初始化,,9.6.3 指向对象的常指针,2019/4/7,58,注意: 指向对象的常指针变量的值不能改变,即始终指向同一个对象,但可以改变其所指向对象(如t1)的值。 如果想将一个指针变量固定地与一个对象相联系(即该指针变量始终指向一个对象),可以将它指定为const型指针变量。 往往用常指针作为函数的形参,目的是不允许在函数执行过程中改变指针变量的值,使其始终指向原来的对象。,2019/4/7,59,为了更容易理解指向常对象的指针变量的概念和使用,首先了解指向
41、常变量的指针变量,然后再进一步研究指向常对象的指针变量。 定义指向常变量的指针变量ptr: const char *ptr; 注意:const的位置在最左侧,它与类型名char紧连,表示指针变量ptr指向的char变量是常变量,不能通过ptr来改变其值的。 定义指向常变量的指针变量的一般形式为: const 类型名 *指针变量名;,9.6.4 指向常对象的指针变量,2019/4/7,60,说明: (1) 如果一个变量已被声明为常变量,只能用指向常变量的指针变量指向它,而不能用一般的(指向非const型变量的)指针变量去指向它。 如: const char c=“boy”; const char
42、 *p1; p1=c; / char *p2=c;/ p2不是指向常变量的指针变量,2019/4/7,61,(2) 指向常变量的指针变量除了可以指向常变量外,还可以指向未被声明为const的变量。此时不能通过此指针变量改变该变量的值。如: char c1=a; const char *p; p=,2019/4/7,62,(3) 如果函数的形参是指向非const型变量的指针,实参只能用指向非const变量的指针,而不能用指向const变量的指针,这样,在执行函数的过程中可以改变形参指针变量所指向的变量(也就是实参指针所指向的变量)的值。 如: const char str=“boy”; void
43、 fun( char *ptr); /形参是非const变量的指针 fun(str); / 实参是const变量的指针,2019/4/7,63,如果函数的形参是指向const型变量的指针,在执行函数过程中显然不能改变指针变量所指向的变量的值,因此允许实参是指向const变量的指针,或指向非const变量的指针。 以上介绍的是指向常变量的指针变量,指向常对象的指针变量的概念和使用是与此类似的,只要将“变量”换成“对象”即可。 (1) 如果一个对象已被声明为常对象,只能用指向常对象的指针变量指向它,而不能用一般的(指向非const型对象的)指针变量去指向它。,2019/4/7,64,(2) 如果定
44、义了一个指向常对象的指针变量,并使它指向一个非const的对象,则其指向的对象是不能通过指针来改变的。如: Time t1(10,12,15); const Time *p=,2019/4/7,65,(3) 指向常对象的指针最常用于函数的形参,目的是在保护形参指针所指向的对象,使它在函数执行过程中不被修改。 如: int main() void fun(const Time *p); Time t1(10,13,56); fun( return 0; ,void fun(const Time *p) p-hour=18; / couthoutendl;,2019/4/7,66,(4) 如果定义
45、了一个指向常对象的指针变量,是不能通过它改变所指向的对象的值的,但是指针变量本身的值是可以改变的。 如: const Time *p= /,2019/4/7,67,引用:一个变量的引用就是变量的别名。实质上,变量名和引用名都指向同一段内存单元。 如果形参为变量的引用名,实参为变量名,则在调用函数进行虚实结合时,并不是为形参另外开辟一个存储空间(常称为建立实参的一个拷贝),而是把实参变量的地址传给形参(引用名),这样引用名也指向实参变量。,9.6.5 对象的常引用,2019/4/7,68,例9.8 对象的常引用。 #include using namespace std; class Time
46、public: Time(int,int,int); int hour; int minute; int sec; ; TimeTime(int h,int m,int s) /定义构造函数 hour=h; minute=m; sec=s; ,void fun(Time ,void fun(const Time &t),不能修改t的值!,2019/4/7,69,在C+面向对象程序设计中,经常用常指针和常引用作函数参数。这样既能保证数据安全,使数据不能被随意修改,在调用函数时又不必建立实参的拷贝。用常指针和常引用作函数参数,可以提高程序运行效率。,2019/4/7,70,9.6.6 const型
47、数据的小结,2019/4/7,71,用前面介绍的方法定义的对象是静态的,在程序运行过程中,对象所占的空间是不能随时释放的。 如果已经定义了一个Box类,可以用下面的方法动态地建立一个对象: Box *pt; /定义一个指向Box类对象的指针变量pt pt=new Box; /在pt中存放了新建对象的起始地址 在程序中就可以通过pt访问这个新建的对象。如 coutheight; /输出该对象的height成员 coutvolume( ); /调用该对象的volume函数,计算并输出体积,9.7 对象的动态建立和释放,2019/4/7,72,在执行new时,对新建立的对象进行初始化。如 Box *pt=new Box(12,15,18); 这种写法是把上面两个语句(定义指针变量和用new建立新对象)合并为一个语句,并指定初值。这样更精炼。新对象中的height,width和length分别获得初值12,15,18。 调用对象既可以通过对象名,也可以通过指针。用new建立的动态对象一般是不用对象名的,是通过指针访问的,它主要应用于动态的数据结构,如链表。,2019/4/7,73,在执行new运算时,如果内存量不足,无法开辟所需的内存空间,则: 返回一个0指针值。 ANSI C+标准提出,
链接地址:https://www.31doc.com/p-2553417.html