第三讲:构造函数概念

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

SchoolofInformationandEngineering,ShenzhenUniversity1构造函数功能:在对象声明时,对对象中的数据成员进行初始化。构造函数的执行:在声明对象时自动执行构造函数的一般形式:构造函数名(形式参数说明){函数体}其中:①不能指定函数类型,哪怕是void也不可以②构造函数名必须和类名相同(这也是构造函数和其它普通函数的根本区别)。23:29:402构造函数设计(ConstructorDesign)初始化要求:对象与变量的不同在于对象对应于事物,要求从诞生之时起便有明确的意义.封装性要求:初始化不是简单的参数与成员对应,而是联系参数到成员的过程.构造函数名:该过程产生对象,而不是捆绑对象的成员函数调用,因而它是特殊的成员函数形式:与变量的定义形式保持一致.构造函数原则上不能失败,也没有返回形式例外:一次性对象构造,没有对象名,与强制转换的形式一致,因而它是一个特定类型的对象.SchoolofInformationandEngineering,ShenzhenUniversity3构造函数中的形式参数形式1:构造函数中的形参说明处为空。指取默认值对数据成员进行初始化。形式2:具体列出某种量作为参数。在创建对象时将依给出的实参值对数据成员进行初始化(一般使用传值)。形式3:用一个已知的对象作为实参(一般使用传引用)。在创建对象时就取已知对象对应数据成员的值对本对象数据成员进行初始化。SchoolofInformationandEngineering,ShenzhenUniversity4classDate//时间类{protected:intyear;intmonth;intday;public:Date()//构造函数,不带参数{year=0;month=1;day=1;}Date(inty,intm,intd)//构造函数,带参数{year=y;month=m;day=d;}Date(Date&obj)//构造函数,以一个已经同类对象为参数{year=obj.year;month=obj.month;day=obj.day;}voidprint(){coutyear/month/dayendl;}};23:29:405构造函数重载(ConstructorOverload)构造函数可以重载,也可以参数默认(注意避免二义性问题):classDate{public:Date(conststring&s);Date(inty=2003,intm=12,intd=1);//...};intmain(){Dated(“2006-12-26”);Datee(2000,12,25);Datef(2001,10);Dateg(2002);Dateh();//...}例23:29:406若类中没有定义构造函数,则系统会默认定义一个无参空函数:classDate{public://相当于定义了Date(){}};intmain(){Dated;//ok//...}例23:29:407任何其他的构造函数定义,都将阻止默认无参空函数的产生:classDate{public:Date(inty,intm,intd){}//...};intmain(){Dated;//error//...}23:29:408类成员初始化(ClassMemberInitializations)classStudentID{inta;public:StudentID(){a=1;cout“StudentId:a\n;}};classStudent{stringname;StudentIDid;public:Student(stringn=noName){cout“Student:+n+\n;name=n;}};intmain(){Students(Randy);}数据成员的空间分配是在构造函数被调用和其过程被执行之间的刹那间完成,在类中有对象成员时,那个刹那间便是调用对象所在类的构造函数,以创建对象空间的时机,左边的程序得到下列运行结果:StudentId:1Student:Randy说明先成员构造,后自身构造.成员构造不见显式调用,而是悄悄调用无参构造函数.23:29:409classStudentID{inta;public:StudentID(intid=0){a=id;cout“StudentId:a“\n”;}};classStudent{stringname;StudentIDid;public:Student(stringn=noName,intssID=0):id(ssID),name(n){cout“Student:n\n;}};intmain(){Students(Randy,98);Studentt(Jenny);}实例若要调用对象成员的有参构造函数,须显式调用,见左边形式.其运行结果为:StudentId:98Student:RandyStudentId:0Student:JennySchoolofInformationandEngineering,ShenzhenUniversity10析构函数问题的引入:创建对象时,理应为新创建的对象分配存储空间,而当对象被撤消时(例如在块中声明的局部对象在块执行结束时,或程序执行结束时),必须释放被撤消对象所占用的空间(并把被释放掉的空间加入空闲链中)特别在动态创建对象时更应该如此(在对象生存期结束时应该立即撤消它并且立即释放被它所占用的存储空间,同时把它并入空闲空间链中)。11功能:在对象被撤消时,执行相应的清理工作,并释放创建对象时由系统分配给对象的存储空间。析构函数定义形式:~类名(){函数体}//~符号不可省去其中:函数名必须与类名相同,不能指定形式参数同时不能指定函数类型,即使void也不可以。举例23:29:4012析构函数(Destructors)对象结束其生命时,会被系统悄悄地销毁(析构).即对象本体空间与名字脱离关系.对象结束生命时,若对象本体与对象实体不同,则需要人为地进行资源释放,以保证对象本体失效之前,资源被收回.23:29:4013定义析构函数的目的:由于对象本体与实体不同,所以要进行对象占有资源的释放工作.一般来说,一个类,若有人为定义的构造函数,则也应该定义析构函数.因为对象创建中有资源要获得分配,则对象失效前必应先释放资源.14析构函数定义及应用的例子#includeiostream.hclassTest{private:intn;floatf;public:Test();//构造函数1Test(intN,floatF);//构造函数2intgetint(){returnn;}floatgetfloat(){returnf;}~Test();//析构函数};Test::Test()//构造函数1定义{n=0;f=0.0;cout\nN=n\tF=fendl;}Test::Test(intN,floatF)//构造函数定义{n=N;f=F;cout\nN=n\tF=fendl;}Test::~Test()//析构函数定义{cout\nDestructorisactive.\n;}voidmain(){cout\n...Enteringmain...\n;Testx;Testy(10,20.5);//创建对象cout\n...Exitingmain...\n;}//演示结束SchoolofInformationandEngineering,ShenzhenUniversity15程序执行结果:...Enteringmain...N=0F=0.0...Exitingmain...Destructorisactive.Destructorisactive.对象生存期结束时系统自动去调用析构函数,用户不必刻意去调用它。SchoolofInformationandEngineering,ShenzhenUniversity16对象成员的初始化问题问题引入:在定义一个类时,使用其它类作为本类的成员。含有对象成员的类的对象的初始化:①先对对象成员进行初始化(调用该类的构造函数);②对类中其他非对象成员的成员进行初始化;SchoolofInformationandEngineering,ShenzhenUniversity17对类中的包含的对象成员进行初始化①不能通过简单赋值来完成对对象成员的初始化;②不能在类定义中直接调用对象成员对应的类的构造函数来进行初始化;③只能在类的构造函数的定义(初始化列表)中分别引用对象成员所属类的构造函数来进行初始化;④如果对象成员所对应类的构造函数需要提供参数时,必须在类定义构造函数的参数表中提供。18类中包含有另一个类的对象(对象成员)的例子#includeiostream.hclassObject{intval;public:Object();//构造函数Object(inti);//构造函数~Object();//析构函数};Object::Object(){val=0;cout\nDefaultconstructorforObject.\n;}Object::Object(inti)//构造函数定义{val=i;cout\nConstructorforObject:valendl;}Object::~Object()//析构函数定义{cout\nDestructorforObject:valendl;}19classContainer//定义新类,它含Object的对象{private:intdate;Objectone;//对象成员Objecttwo;//对象成员public:Container();//构造函数Container(inti,intj,intk);//构造函数~Container();//析构函数};Container::Container()//构造函数定义{date=0;cout\nDefaultconstructorforContainer.\n;}Container::Container(inti,intj,intk):two(i),one(j){date=k;cout\nConstructorforContainer.\n;}Container::~Container(){cout\nDestructorforContainer.\n;}voidmain()//演示程序{cout\n...Enteringmain...\n;Containerobj(5,6,10);cout\n...Exitingmain...\n;}20执行结果为:...Enteringmain...ConstructorforObject:6//对象one调用构造函数ConstructorforObject:5//对象two调用构造函数ConstructorforContainer.//调用Container构造函数...Exitingmain...DestructorforContainer.//调用Container析构函数DestructorforObject:5//调用two的析构函数DestructorforObject:6//调用one的析构函数23:29:4121同一工程不同代码文件全局对象的创建没有明确顺序规定.对策:不要让不同文件的全局对象互为依赖.因为依赖具有先后性,而其全局对象的创建不能保证该依赖性发挥作用.全局对象在main函数启动之前生成,而调试则在main函数启动之后.对策:调试时,应先将全局对象作为局部对象来运行观察.或者,在构造函数中添加输出语句来观察运行过程.23:29:4122成员对象的构造顺序按类定义的出现顺序,最后执行自身构造函数:classA{

1 / 32
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功