《第二部分面向对象程序设计.ppt》由会员分享,可在线阅读,更多相关《第二部分面向对象程序设计.ppt(50页珍藏版)》请在三一办公上搜索。
1、,第二部分面向对象程序设计,第十一章构造函数和析构函数,11,11.1 类与对象,第十一章 目 录,11.3 析构函数,11.2 构造函数,11.4 带参数的构造函数,11.5 重载构造函数,11.6 缺省构造函数,第十一章小结,11.7 拷贝构造函数,11.8 拷贝构造函数的其他用处,C+中构造函数和析构函数是类的特殊成员函数。构造函数用于创建类对象,初始化其成员。析构函数用于撤销类对象。本章介绍构造函数、析构函数、缺省构造函数、拷贝构造函数等相关内容。,第十一章 构造函数和析构函数,一个类描述一类事物,描述这些事物所应具有的属性。对象是类的一个实例,它具有确定的属性。如学生类与某学生对象。
2、类的名字只有一个,但由该类创建的对象可以任意多个。属于不同类的对象可以在不同时刻、不同环境分别创建或撤销。与定义变量相同,可定义具有不同存储属性的各类对象。定义对象时,C+编译器为其分配存储空间(如果需要)。,11.1 类与对象,例如:下面程序定义了两个类,创建了全局对象和局部对象,静态对象和堆对象。class Desk/define class Desk public:int weight;int high;int width;int length;class Stool/define class Stool public:int weight;int high;,int width;int
3、 length;Desk da;/globle object daStool sa;/globle object savoid fn()static Stool ss;/local static object Desk da;/local object/void main()Stool bs;/local object Desk*pd=new Desk;/heap object,Desk nd50;/local array of object/delete pd;/clean up object and release resources 前面已经介绍过变量定义时若未显式初始化,全局变量和静态
4、变量在定义时初值为0,局部变量在定义时初值为随机数。与定义变量不同,一旦建立一个对象,对象通常都需要有一个有意义的初值。C+建立和初始化对象的过程专门由该类构造函数完成。对象建立时,调用该构造函数,给对象分配存储空间并进行初始化。当对象撤销时,调用析构函数作善后处理。,11.2 构造函数,类创建对象时需要对对象初始化,但初始化任务,只有由成员函数完成,因此,在类中必须定义一个具有初始化功能的成员函数。每当创建一个对象时,就调用这个成员函数,实现初始化。例如:class Student public:void init()semeshours=100;gpa=3.5;,/protected:in
5、t semeshours;int gpa;void fn()Student s;s.init();/调用类的初始化函数/这种将初始化工作交由初始化成员函数完成的方式使系统多了一道处理过程,增加了书写代码,实现的机制并不理想。,另一种方法是建立对象的同时,自动调用构造函数,省去上述麻烦,使定义类对象时包含了为对象分配存储空间和初始化的双重任务。这种实现机制较为理想。由于类的唯一性和对象的多样性,因此C+规定构造函数与类同名。其特点是:Constructor is a function with the explicit purpose of initializing object.Because
6、 such a function constructs values of a given type,it is called a constructor.A constructor is recognized by having the same name as the class itself.When a class has a constructor,all objects of that class will be initialized by a constructor call.,构造函数的使用方式有:构造函数在类体内定义,例如:#include class Desk publi
7、c:Desk()weight=10;high=5;width=5;length=5;protected:int weight;int high;,int width;int length;void fn()Desk da;/constructor call/,构造函数可以在类体外定义,例如:#include class Desk public:Desk();,protected:int weight;int high;int width;int length;Desk:Desk()/constructor definition weight=10;high=5;width=5;length=5
8、;coutweight“”high“”width“”lengthendl;,void fn()Desk da;void main()fn();结果:10 5 5 5,da 对象的内存空间分配及初始化,weight,high,width,length,da,若将fn()函数改为void fn()Desk dd5;则执行定义数组语句时,构造函数将被调用5 次,即对每个数组成员对象的创建都要调用一次构造函数。,weight,high,width,length,weight,high,width,length,dd0,dd4,dd5 对象的内存空间分配及初始化,输出结果为:5 5 510 5 5 55
9、 5 510 5 5 510 5 5 5,注意:1、类体外定义构造函数,其函数名前要加上“类名:”;2、构造函数无返回类型;3、在定义时,若类的数据成员是另一个类的对象,则在调用构造函数创建对象时,对作为数据成员的对象先要自动调用其自身的构造函数。下面程序的Tutorpair类(“帮教派对”)中,其成员包含有学生类对象和老师类对象。程序说明了调用构造函数的方法。,/ch11-5.cpp#include class Student public:Student()cout“Constructing student.n”;semeshours=100;gpa=3.5;/protected:int
10、semeshours;float gpa;,class Teacher public:Teacher()cout“Constructing teacher.n”;class Tutorpair public:Tutorpair()cout“Constructing tutorpair.n”;nomeetings=0;,protected:Student student;/class object as member data Teacher teacher;/class object as member data int nomeetings;void main()Tutorpair tp;c
11、out“Back in main.n”;,运行结果:Constructing student.Constructing teacher.Constructing Tutorpair.Back in main.,当调用构造函数Tutorpair()创建的对象tp 时,首先根据对象成员被说明的次序,依次调用Student()构造函数和Teacher()构造函数创建成员对象Student 和Teacher,然后执行它自己的构造函数的函数体,如运行结果所示。,The constructor is used to initialize objects,and destructor is used to
12、clean up objects and release resources before they are become unusable.例如在下面情况下需要使用析构函数:一个对象当结束其生命期时,比如在函数体内定义的对象,当该函数调用结束时,局部对象被释放。构造函数打开一个文件,使用完文件时,需要关闭文件。从堆中分配了动态内存区,在对象消失之前必须释放。,11.3 析构函数,析构函数的特点:无返回类型;无参数;不能随意调用;不能重载。而构造函数可以有参数,也可以重载。析构函数与构造函数的功能相对应,所以析构函数名是构造函数名前加一个逻辑反运算符“”,例如:下面程序段在class Xyz
13、类中定义了一个构造函数和一个析构函数。class Xyz public:Xyz()/constructor definition name=new char20;Xyz()/destructor definition delete name;protected:char*name;,该类定义的构造函数在对象之外分配一段堆内存空间,撤销时,由析构函数收回堆内存。注意,析构函数以调用构造函数相反的顺序被调用。例如:在ch11-5.cpp 程序中为每个类增加析构函数则有:/ch11-7.cpp#include class Student public:Student()cout“Constructi
14、ng student.n”;semeshours=100;gpa=3.5;,Studeng()cout“Destructing student.n”;protected:int semeshours;float gpa;class Teacher public:Teacher()cout“Constructing teacher.n”;,Teacher()cout“Destructing teacher.n”;class Tutorpair public:Tutorpair()cout“Constructing tutorpair.n”;nomeetings=0;Tutorpair()cout
15、“Destructing tutorpair.n”;,protected:Student student;Teacher teacher;int nomeetings;void main()Tutorpair tp;cout“Back in main.n”;,Constructing student.,Constructing teacher.,Constructing tutorpair.,Back in main.,Destructing tutorpair.,Destructing teacher.,Destructing student.,运行结果:,不带参数的构造函数不能完全满足初始
16、化的要求,因为这样创建的类对象具有相同的初始化值。如果需要对类对象按不同特征初始化不同的值,应采用带参数的构造函数。如下面程序所示:/tdate1.h class Tdate1 public:Tdate1(int y,int m,int d);Tdate1();void print();,11.4 带参数的构造函数,private:int year,month,day;Tdate1:Tdate1(int y,int m,int d)year=y;month=m;day=d;cout“Constructor called.n”;Tdate1:Tdate1()cout“Destructor cal
17、led.n”;void Tdate1:print()coutyear“.”month“.”dayendl;,#include#include“tdate1.h”void main()Tdate1 today(2001,5,1),tomorrow(2001,5,2);cout“Today is”;today.print();cout“Tomorrow is”;tomorrow.print();,结果:Constructor called.Constructor called.Today is 2001.5.1Tomorrow is 2001.5.2Destructor called.Destru
18、ctor called.,注意:构造函数可采用以下两种方式将值赋给其成员。1、在构造函数体内进行成员变量的赋值,如前例中所示,又如:class X int a,b;/default private public:X(int i,int j)a=i;b=j;/value assigned within constructor;2、使用函数体前的初始值表,例如:class X int a,b;public:X(int i,int j):a(i),b(j);,下面是使用构造函数创建对象,使用析构函数撤销对象的另一个例子。/ch11-9.cpp#include#include class Studen
19、t public:Student(char*pname,int xhours,int xgpa)cout“Constructing student”pnameendl;,strncpy(name,pname,sizeof(name);namesizeof(name)-1=0;semeshours=xhours;gpa=xgpa;Student cout“Destructing”nameendl;/其它成员函数 protected:char name20;int semeshours;float gpa;,void main()Student one(“Li ming”,22,3.5);/运行结
20、果:Constructing student Li mingDestructing Li ming创建对象one 的情况如下:学生名“Li ming”name20 学期学时数 22 semeshours 平均成绩 3.5 gpa,构造函数可以被重载,C+根据类体中声明构造函数的参数类型和个数选择合适的构造函数。例如:下面程序中声明了4 个重载的构造函数/ch11-9.cpp#include class Tdate public:Tdate();Tdate(int d);Tdate(int m,int d);Tdate(int m,int d,int y);/.,11.5 重载构造函数,prot
21、ected:int month,day,year;Tdate:Tdate()mothe=4;day=15;year=1995;coutmonth“/”day“/”yearendls;Tdate:Tdate(int d)mothe=4;day=d;year=1996;coutmonth“/”day“/”yearendls;Tdate:Tdate(int m,int d)mothe=m;day=d;year=1997;coutmonth“/”day“/”yearendls;,Tdate:Tdate(int m,int d,int y)mothe=m;day=d;year=y;coutmonth“/
22、”day“/”yearendls;void main()Tdate aday;Tdate bday(10);Tdate cday(2,12);Tdate dday(1,2,1998);,结果为:4/15/1995 4/10/1996 2/12/1997 1/2/1998,A default constructor is a constructor that can be called without supplying an argument.If a user has declared a default constructor.that one will be used;otherwise
23、,the compiler will try to generate one if needed,and if the user hasnt declared other constructors.,11.6 缺省构造函数(Default Constructors),1、C+规定,每一个类必须有一个构造函数,没有构造函数就不能创建任何对象;2、若未定义一个类的构造函数,则C+提供了一个缺省的构造函数,该缺省构造函数是一个无参数的构造函数,仅仅负责创建对象,而不做任何初始化工作;3、只要一个类定义了一个构造函数,C+就不再提供缺省的构造函数。如还需要无参数构造函数,则必须自己定义;4、与变量定义
24、类似,在用缺省构造函数创建对象时,如果创建的是全局对象或静态对象,则对象成员数据全为0;局部对象创建时,其成员数据是无意义的随机数。本章第一个例子中,创建的全局对象、静态对象及局部对象都是由编译器提供的缺省构造函数自动创建的,仅对成员数据分配了内存空间,未做初始化工作。,C+中,提供了用一个对象值创建并初始化另一个对象的方法,完成该功能的是拷贝构造函数。例如:Tdate d1(2002,3,1);Tdate d2(d1);用构造函数创建d1 的值初始化新创建的对象d2。拷贝构造函数的特点:1、拷贝构造函数名字与类同名,没有返回类型;2、拷贝构造函数只有一个形参数,该参数是该类的对象的引用;,1
25、1.7 拷贝构造函数(Copy Constructor),3、拷贝构造函数的格式如下::(/copy constructor declaration,Tpoint()cout“Destructor called.n”;int xcoord()return x;int ycoord()return y;private:int x,y;Tpoint:Tpoint(Tpoint,void main()Tpoint p1(5,7);Tpoint p2(p1);cout“p2=”p2.xcoord()“,”p2.ycoord()endl;,结果:Copy_initialization construct
26、or called.P2=5,7Destructor called.Destructor called.,拷贝构造函数除了用于使用已知对象的值创建一个同类的新对象外,还有两个主要用处:1、把对象作为实参数进行函数调用时,系统自动调用拷贝构造函数实现把对象值传递给形参对象;2、当函数的返回值为对象时,系统自动调用拷贝构造函数对返回对象值创建一个临时对象,然后再将这个临时对象值赋给接收函数返回值的对象。例如:下面程序中共创建了7 个对象,使用了3 次拷贝构造函数。,11.8 拷贝构造函数的其他用处,#include“tpoint.h”Tpoint fun(Tpoint q);void main()
27、Tpoint M(12,20),P(0,0),S(0,0);Tpoint N(M);P=fun(N);S=M;cout“P=”P.xcoord()“,”P.ycoord()endl;cout“S=”S.xcoord()“,”S.ycoord()endl;Tpoint fun(Tpoint q)cout“OKn”;int x=q.xcoord()+10;int y=q.ycoord()+15;,Tpoint R(x,y);return R;/tpoint.h#include class Tpoint public:Tpoint(int xp,int yp)x=xp;y=yp;Tpoint(Tpo
28、int,Tpoint:Tpoint(Tpoint输出结果如下:Copy_initialization constructor called.Copy_initialization constructor called.OKCopy_initialization constructor called.Destructor called.Destructor called.Destructor called.,P=22,35 S=12,20 Destructor called.Destructor called.Destructor called.Destructor called.程序输出结果说
29、明程序中出现了三次调用构造函数:Tpoint N(M);/M 对象创建N 对象P=fun(N);/实参N 对象被拷贝到形参q对象return R;/函数返回时,调用拷贝构造函数,用对象R创建/一个临时对象,保存R 的数据,在主函数中临/时对象被释放前,将它的内容赋值到对象P 中。,临时对象起暂存作用的情况如下图所示:,构造函数是一种用于创建对象的特殊成员函数,调用它为类对象分配空间,给它的数据成员赋初值,以及其他请求资源的工作。析构函数是一种用于撤销对象,回收对象占有资源的特殊成员函数,它与构造函数功能互补,成对出现。每个类对象都必须在构造函数中诞生,一个类可能定义一个或多个构造函数,编译程序按对象构造函数声明中使用的形参数与创建对象的实参数比较,确定使用哪个构造函数,这与普通重载函数的使用方法类似。,十 一 章 小 结,在包含有对象成员的类对象被创建时,需要对对象成员进行创建,相应地要调用对象成员的构造函数。拷贝构造函数用于由一个已知的对象创建一个新对象。缺省构造函数和缺省析构函数用于在类中未显式定义构造函数和析构函数的情况,以创建一个对象(只分配数据成员的存储空间,不能初始化值),自动调用缺省的析构函数,以撤销一个对象并回收资源。,
链接地址:https://www.31ppt.com/p-4525241.html