1、版本号:V2006.12,C+程序设计(第2版),第4章 类与对象,在C+中,对象的数据成员的初始化可以有三种方法: 使用初始化数据列表的方法; 通过构造函数; 通过对象的拷贝初始化函数;构造函数:是在类体中说明的一种特殊的成员函数,其功能是在创建类的对象时,使用给定的值将对象初始化。在定义一个类时,可以根据需要定义一个或多个构造函数(重载构造函数)。构造函数与类的成员函数一样,可以在类中定义,也可以在类外定义。,4.3 构造函数与析构函数,4.3.1 构造函数及对象的初始化,一般格式为: ClassName() 或者: ClassName:ClassName() ,例4.5 使用构造函数对新
2、产生的对象初始化 #include class Cint i; public:char *name; protected:float num2;,public:C(int a, char *s, float x, float y) i=a;name=s;num0=x; num1=y;void Print(void) coutitnamet;coutnum0tnum1n; ; void main(void) C c1(25,“name“,77.8f,99.56f);c1.Print( ); 运行结果: 25 Name 77.8 99.56,构造函数的函数名必须与类名相同。系统在生成类的对象时自动
3、调用类的构造函数,完成初始化对象的成员数据工作。 构造函数的定义不能指定函数的返回值类型,也不能指定为void类型。 构造函数可以不带参数,也可以带若干个参数或指定参数的缺省值,构造函数允许重载。 若定义的类要用来说明类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其他类时,则可将构造函数定义为保护的成员函数。,对构造函数的几点说明:,#include class Rectangleint Left, Right, Top, Bottom; public:Rectangle(int L, int R, int T, int B)Left =L; Right=R;Top=T; B
4、ottom=B;cout“调用带参数的构造函数(全局)!n“;Rectangle(int L, int R, int T)Left =L; Right=R;Top=T; Bottom=0;cout“调用带参数的构造函数(静态)!n“;,例4.6 产生全局对象、静态对象和局部对象,Rectangle(int L, int R)Left =L; Right=R;Top=0; Bottom=0;cout“调用带参数的构造函数(局部)!n“;Rectangle( )Left=0;Right=0;Top=0;Bottom=0;cout“调用不带参数的构造函数!n“;void Print(void)cou
5、tLefttRighttToptBottomn; ;,Rectangle r4(200,300,400,500); /全局对象,在进入main( )之前调用 void f1(void) cout“进入函数f1( )n“;static Rectangle r5(200,200,500); /静态对象r5只在首次调用函数f1并产生该对象时调用构造函数;r5.Print( ); Rectangle r6(100,100); /局部对象r6,每次调用f1时都要调用构造函数。r6.Print( ); ,void main(void) cout“进入主函数main( )n“;r4.Print( );f1(
6、 );Rectangle r1(100,200);r1.Print( );Rectangle r2;r2.Print( );f1( ); ,说明:在函数f1中,B行中定义的静态对象r5是在首次调用函数f1并产生该对象时调用构造函数的,第二次调用函数f1时,不再重新产生对象r5。而局部对象r6,每次调用函数f1时都要调用构造函数。,ClassName:ClassName( ) ;缺省构造函数并不对所产生对象的数据进行任何初始化操作。说明: 在定义类时,若定义了类的构造函数,则系统不产生缺省的构造函数。 若定义了不带参数或各参数均有缺省值的构造函数,同为缺省构造函数。 产生对象时,由于系统必定要调
7、用构造函数,因此任一对象的构造函数必须唯一。,缺省的构造函数,在定义类时,若没有定义类的构造函数,则编译器自动产生一个缺省的构造函数,其格式为:,class Eint x, y; Public:E(int a, int b)x=a; y=b;void P(void)coutxtyn; ; 对于:E e; 错误:产生对象e时,没有缺省的构造函数可调用。,Class Qint x, y; Public:Q(int a=0, int b=0)x=a; y=b;Q( ) ;void P(void)coutxtyn; ; 对于:Q q; 错误:编译时指出同时有两个缺省构造函数,在产生对象q时,无法确定。
8、,class Rint x, y; public:R(int a, int b)x=1; y=b; 如果有说明: R r( ); 则编译器认为这不是定义对象r,而是函数原型说明。认为函数r( )的返回值为类R类型。,与构造函数的功能正好相反,析构函数的功能是用来释放一个对象的。在对象删除前,用它来做一些清理工作。 析构函数的定义与构造函数定义相似,只是在函数名前加上一个“”号。例:ClassName( );,4.3.2 析构函数,析构函数的特点如下:1。析构函数是成员函数,函数体可写在类体内,也可在内体外。 2。析构函数也是一个特殊的函数,它的名字同类名,并在前面加“”字符,用来与构造函数区别
9、。析构函数不指定数据类型,并且没有参数。 3。一个类中只可能定义一个析构函数,析构函数不允许重载。 4。析构函数是在撤消对象时由系统自动调用,也可以被独立调用。,下面两种情况下,析构函数会被自动调用: (1)如果一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用。 (2)当一个对象是使用new运算符被动态创建的,在使用delete运算符释放它时, delete将会自动调用析构函数。 5. 在析构函数内不能使用exit系统函数来终止程序的执行,因为exit函数要做终止程序前的结束工作,这将再次调用析构函数形成递归。但可以使用about函数,这是因为about不做终止前的结束工作,直接终止程序的执行。 6. 若在类的定义中没有显式的定义析构函数,则编译器自动地产生一个缺省的析构函数,其格式为: ClassName:ClassName( ) ;,