您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 第10章构造函数和析构函数.
第十章构造函数和析构函数构造函数和析构函数是在类体中说明的两种特殊的成员函数。构造函数是在创建对象时,使用给定的值来将对象初始化。析构函数的功能正好相反,是在系统释放对象前,对对象做一些善后工作。构造函数是类的成员函数,系统约定构造函数名必须与类名相同。构造函数提供了初始化对象的一种简单的方法。构造函数可以带参数、可以重载,同时没有返回值。classA{floatx,y;public:A(floata,floatb){x=a;y=b;}//构造函数,初始化对象floatSum(void){returnx+y;}voidSet(floata,floatb){x=a;y=b;}Print(void){coutx=x'\t'y=yendl;}};voidmain(void){Aa1(2.0,3.0);//定义时调用构造函数初始化Aa2(1.0,2.0);a2.Set(10.0,20.0);//利用成员函数重新为对象赋值a1.Print();a2.Print();}对构造函数,说明以下几点:1.构造函数的函数名必须与类名相同。构造函数的主要作用是完成初始化对象的数据成员以及其它的初始化工作。2.在定义构造函数时,不能指定函数返回值的类型,也不能指定为void类型。3.一个类可以定义若干个构造函数。当定义多个构造函数时,必须满足函数重载的原则。4.构造函数可以指定参数的缺省值。5.若定义的类要说明该类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其它类时,则可将构造函数定义为保护的成员函数。由于构造函数属于类的成员函数,它对私有数据成员、保护的数据成员和公有的数据成员均能进行初始化。classA{floatx,y;public:A(floata,floatb=10){x=a;y=b;}A(){x=0;y=0;}voidPrint(void){coutx'\t'yendl;}};voidmain(void){Aa1,a2(20.0),a3(3.0,7.0);a1.Print();a2.Print();a3.Print();}00201037带缺省参数的构造函数不带参数的构造函数每一个对象必须要有相应的构造函数每一个对象必须要有相应的构造函数若没有显式定义构造函数,系统默认缺省的构造函数。classA{floatx,y;public:A(){}voidPrint(void){coutx'\t'yendl;}};隐含的缺省的构造函数Aa1,a2;只允许这样定义对象对象开辟了空间,但没有初始化对局部对象,静态对象,全局对象的初始化对于局部对象,每次定义对象时,都要调用构造函数。对于静态对象,是在首次定义对象时,调用构造函数的,且由于对象一直存在,只调用一次构造函数。对于全局对象,是在main函数执行之前调用构造函数的。classA{intx,y;public:A(inta){x=a;cout“1\n”;}A(inta,intb){x=a,y=b;cout“2\n”;}};Aa1(3);voidf(void){Ab(2,3);}voidmain(void){Aa2(4,5);f();f();}1222classA{floatx,y;public:A(floata,floatb){x=a;y=b;cout初始化自动局部对象\n;}A(){x=0;y=0;cout初始化静态局部对象\n;}A(floata){x=a;y=0;cout初始化全局对象\n;}voidPrint(void){coutx'\t'yendl;}};Aa0(100.0);//定义全局对象voidf(void){cout进入f()函数\n;Aa2(1,2);staticAa3;//初始化局部静态对象}voidmain(void){cout进入main函数\n;Aa1(3.0,7.0);//定义局部自动对象f();f();}初始化全局对象进入main函数初始化自动局部对象进入f()函数初始化局部静态变量进入f()函数初始化自动局部对象初始化自动局部对象缺省的构造函数在定义类时,若没有定义类的构造函数,则编译器自动产生一个缺省的构造函数,其格式为:className::className(){}缺省的构造函数并不对所产生对象的数据成员赋初值;即新产生对象的数据成员的值是不确定的。classA{floatx,y;public:A(){}//缺省的构造函数,编译器自动产生,可以不写floatSum(void){returnx+y;}voidSet(floata,floatb){x=a;y=b;}voidPrint(void){coutx=x'\t'y=yendl;}};voidmain(void){Aa1,a2;//产生对象时,自动调用缺省的构造函数,不赋值a1.Set(2.0,4.0);couta1:;a1.Print();couta1.sum=a1.Sum()endl;a2.Print();//打印随机值}关于缺省的构造函数,说明以下几点:1、在定义类时,只要显式定义了一个类的构造函数,则编译器就不产生缺省的构造函数2、所有的对象在定义时,必须调用构造函数不存在没有构造函数的对象!classA{floatx,y;public:A(floata,floatb){x=a;y=b;}voidPrint(void){coutx'\t'yendl;}};voidmain(void){Aa1;Aa2(3.0,30.0);}显式定义了构造函数,不产生缺省的构造函数error,定义时,没有构造函数可供调用3、在类中,若定义了没有参数的构造函数,或各参数均有缺省值的构造函数也称为缺省的构造函数,缺省的构造函数只能有一个。4、产生对象时,系统必定要调用构造函数。所以任一对象的构造函数必须唯一。classA{floatx,y;public:A(floata=10,floatb=20){x=a;y=b;}A(){}voidPrint(void){coutx'\t'yendl;}};voidmain(void){Aa1;Aa2(3.0,30.0);}两个函数均为缺省的构造函数两个构造函数均可供调用,构造函数不唯一构造函数与new运算符可以使用new运算符来动态地建立对象。建立时要自动调用构造函数,以便完成初始化对象的数据成员。最后返回这个动态对象的起始地址。用new运算符产生的动态对象,在不再使用这种对象时,必须用delete运算符来释放对象所占用的存储空间。用new建立类的对象时,可以使用参数初始化动态空间。classA{floatx,y;public:A(floata,floatb){x=a;y=b;}A(){x=0;y=0;}voidPrint(void){coutx'\t'yendl;}};voidmain(void){A*pa1,*pa2;pa1=newA(3.0,5.0);//用new动态开辟对象空间,初始化pa2=newA;//用new动态开辟空间,调用构造函数初始化pa1-Print();pa2-Print();deletepa1;//用delete释放空间deletepa2;//用delete释放空间}3500析构函数析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统为对象所分配的空间,即要撤消一个对象。析构函数也是类的成员函数,定义析构函数的格式为:ClassName::~ClassName(){......//函数体;}析构函数的特点如下:1、析构函数是成员函数,函数体可写在类体内,也可写在类体外。2、析构函数是一个特殊的成员函数,函数名必须与类名相同,并在其前面加上字符“~”,以便和构造函数名相区别。3、析构函数不能带有任何参数,不能有返回值,不指定函数类型。在程序的执行过程中,当遇到某一对象的生存期结束时,系统自动调用析构函数,然后再收回为对象分配的存储空间。4、一个类中,只能定义一个析构函数,析构函数不允许重载。5、析构函数是在撤消对象时由系统自动调用的。classA{floatx,y;public:A(floata,floatb){x=a;y=b;cout调用非缺省的构造函数\n;}A(){x=0;y=0;cout调用缺省的构造函数\n;}~A(){cout调用析构函数\n;}voidPrint(void){coutx'\t'yendl;}};voidmain(void){Aa1;Aa2(3.0,30.0);cout退出主函数\n;}调用缺省的构造函数调用非缺省的构造函数退出主函数调用析构函数调用析构函数在程序的执行过程中,对象如果用new运算符开辟了空间,则在类中应该定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间。因为在撤消对象时,系统自动收回为对象所分配的存储空间,而不能自动收回由new分配的动态存储空间。classStr{char*Sp;intLength;public:Str(char*string){if(string){Length=strlen(string);Sp=newchar[Length+1];strcpy(Sp,string);}elseSp=0;}voidShow(void){coutSpendl;}~Str(){if(Sp)delete[]Sp;}};voidmain(void){Strs1(StudyC++);s1.Show();}在构造函数中将成员数据指针指向动态开辟的内存用初值为开辟的内存赋值析构函数,当释放对象时收回用new开辟的空间‘S’‘t’‘u’‘d’‘y’‘’‘C’‘+’‘+’‘\0’stringLength=strlen(string);Sp=newchar[Length+1];Spnew开辟的空间strcpy(Sp,string);‘S’‘t’‘u’‘d’‘y’‘’‘C’‘+’‘+’‘\0’用new运算符为对象分配动态存储空间时,调用了构造函数,用delete删除这个空间时,调用了析构函数。当使用运算符delete删除一个由new动态产生的对象时,它首先调用该对象的析构函数,然后再释放这个对象占用的内存空间。可以用new运算符为对象分配存储空间,如:A*p;p=newA;这时必须用delete才能释放这一空间。deletep;classA{floatx,y;public:A(floata,floatb){x=a;y=b;cout调用了构造函数\n;}voidPrint(void){coutx'\t'yendl;}~A(){cout调用了析构函数\n;}};voidmain(void){cout进入main()函数\n;A*pa1;pa1=newA(3.0,5.0);//调用构造函数pa1-Print();deletepa1;//调用析构函数cout退出main()函数\n;}进入main()函数调用了构造函数35调用了析构函数退出main()函数不同存储类型的对象调用构造函数及析构函数1、对于全局定义的对象(在函数外定义的对象),在程序开始执行时,调用构造函数;到程序结束时,调用析构函数。2、对于局部定义的对象(在函数内定义的对象),当程序执行到定义对象的地方时,调用构造函数;在退出对象的作用域时,调用析构函数。3、用static定义的局部对象,在首次到达对象的定义时调用构造函数;到程序结束时,调用析构函数4、对于用new运算符动态生成的对象,在产生对象时调用构造函数,只有使用delete运算符来释放对象时,才调用析构函数。若不使用delete来撤消动态生成的对象,程序结束时,对象仍存在,并占用相应的存储空间,即系统不能自动地调用析构函数来撤消动态生成的对象。classA{floatx,y;pub
本文标题:第10章构造函数和析构函数.
链接地址:https://www.777doc.com/doc-2152995 .html