190 likes | 332 Views
第三章构造函数和析构函数. 构造函数初始化对象:. 构造函数的 名字必须与类名相同 构造函数可有任意类型的参数, 但不能有返回类型 定义对象后,编译系统会 自动地调用 构造函数 构造函数可以是不带参数的 构造函数也可采用初始化表对数据成员进行初始化。. class A{ int i; char j; float f; public: A(int I,char J,float F):i(I),j(J),f(F) { }}; void main() { A(1,2,3);}. 第三章构造函数和析构函数. 构造函数和运算符 new
E N D
第三章构造函数和析构函数 • 构造函数初始化对象: • 构造函数的名字必须与类名相同 • 构造函数可有任意类型的参数,但不能有返回类型 • 定义对象后,编译系统会自动地调用构造函数 • 构造函数可以是不带参数的 • 构造函数也可采用初始化表对数据成员进行初始化。 class A{ int i; char j; float f; public: A(int I,char J,float F):i(I),j(J),f(F) { }}; void main() { A(1,2,3);}
第三章构造函数和析构函数 • 构造函数和运算符new • new建立动态对象 • 对没有定义构造函数的类,其公有数据成员可以用初始值表进行初始化 class Init{ public: int i; char *name; float num[2];}; Init C={34,”program”,{56.89,1.2}}; • 缺省参数的构造函数
第三章构造函数和析构函数 class complex{ private: double real; double imag; public: complex(double r=0.0,double i=0.0); }; complex::complex(double r,double i) {real=r;imag=i;} void main( ) { complex s1; complex s2(1.1); complex s3(1.1,2.2);} 注意:避免重载没有参数和带缺省参数的构造函数
第三章构造函数和析构函数 • 复制初始化构造函数:依据已存在的对象建立新对象 X::X(X&) class point{ int x,y; public: point(){} point(int a,int b) {x=a;y=b;} point(point &p) {x=2*p.x;y=2*p.y;} void print(){cout<<x<<" "<<y<<endl;}}; void main() {point p1(30,40); point p2(p1); point p3=p1; // 比较复制p2=p1;p3=p1; p1.print(); p2.print();}
第三章构造函数和析构函数 • 析构函数:删除对象 • 运算符delete:删除动态对象 • 对象数组:为对象数组的每个元素调用一次析构函数 • delete []ptr;
第三章构造函数和析构函数 • 构造函数类型转换 class Test{ private:int num; public: ~Test(){cout<<“Destroying”<<num<<endl;} Test(int n){num=n;cout<<“Initialing”<<num<<endl;} void print(){cout<<num<<endl;} }; void main() {Test try1(0); try1=5; try1.print(); try1=Test(10); try1.print();} 比较Test try1=5;
第三章构造函数和析构函数 int i; class Test{ private:int num; public: ~Test(){i=num;cout<<“Destroying”<<i<<endl;} Test(int n){num=n;cout<<“Initialing”<<num<<endl;}}; void main() {i=1; Test try1(1); try1=5; try1=Test(10); } Initialing1 Initialing5 Destroying5 Initialing10 Destroying10 Destroying10
第三章构造函数和析构函数 • 对象的初始化:对象用作函数的参数以及函数返回一个对象 • 类的数据成员含有指针变量时,要自定义拷贝构造函数 • 以值调用方式向函数传递对象参数时,为初始化形参,要调用复制初始化构造函数,被调函数返回时,析构函数被调用。 • 函数返回值为对象时,要调用拷贝构造函数,结束时调用析构函数 • 对象赋值时不调用拷贝构造函数,而是调用operator=()函数 • 引用作为函数的参数,不调用复制构造函数和析构函数 • P51例题
第三章构造函数和析构函数 • 对象成员: • 说明: • 具有对象成员的构造函数 • X::X(参数表0):成员1(参数表1)…{…} • 对对象成员的构造函数的调用顺序取决于对象成员在类中说明的顺序 • 当建立X类的对象时,先调用对象成员的构造函数,然后再执行其它的构造函数 • 当初始化const成员和引用成员时,必须通过成员初始化列表进行 class example{ private: const int num; int& ref; public:example(int n,int f):num(n),ref(f){}};
勘误表 P45:exit(0)表示正常结束,所有文件关闭,输出缓冲区内容写入磁盘,调用exit时,在当前作用域的任何局部变量不会引起析构函数的调用,全局变量仍调用析构函数。 abort表示引起一个异常程序终止,但不调用析构函数,即使对于全局对象也不调用析构函数 P48(例题注释) //建立对象Try //建立隐藏对象 //析构隐藏对象5 //输出建立的对象Try的数据 //由强制类型转换建立数据为10的对象 //析构Test(10)建立的隐藏对象 //输出对象Try的值 //析构对象Try
勘误表 • P57 程序1的输出的第四行开始 Destructor for container Destructor for object 5 Destructor for object 6 程序2的输出的第四行开始 Destructor for container Destructor for object 0 Destructor for object 0
例题分析 class Location{ //改错 private:int X,Y; protected:int Z; public: void Init(int initX,int initY,int initZ){X=initX;Y=initY;Z=initZ;} Location(int m,int n,int l):X(m),Y(n),Z(l){ } int GetX(){return X;} int GetY(){return Y;} }; void main() {Location A3; A3.Init(785,980); cout<<A3.Z; }
例题分析 B • 对于任意一个类,析构函数的个数最多为: A.0 B.1 C.2 D.3 C • 类的构造函数被自动调用执行的情况是在定义该类的 • A.成员函数时 B.数据成员时 C.对象时 D.友元函数时 无参 • 定义类的动态对象数组时,系统只能自动调用该类的 构造函数对其进行初始化 拷贝 • 假定AB为一个类,则语句AB(AB&x);为该类构造函数的原型说明 • 假定用户没有给一个名为AB的类定义析构函数,则系统自动给出的缺省析构函数定义为 ~AB() 析构 • 删除动态对象时,将自动调用该动态对象所属类的函数
例题分析 指出下面程序段中的错误,并说明错误原因 class A{ int a,b; public: A(int aa,int bb){a=aa;b=bb;} }; A x(2,3),y(4); y(4)错,参数的个数不对 此类定义有一处错误,请指出错误并改正 class ABC{ int a; public: ABC(int aa)a(aa){} }; ABC(int aa){a=aa;}
例题分析 指出下面程序段中的错误,并说明错误原因 class Location{ int X,Y=20; protected: int zeroX,zeroY; int SetZero(int ZeroX,int ZeroY); private: int length,height; public: float radius; void init(int initX,int initY); int GetX(); int GetY(); }; 该句错误,不能采用这种方式初始化
例题分析 指出下面程序段中的错误,并说明错误原因 class Location{ int X,Y; protected: int zeroX,zeroY; int SetZero(int zeroX,int zeroY){X=zeroX;Y=zeroY;} private: int length,height; public: float radius; void init(int initX,int initY){length=initX;height=initY;} int GetX(){return X;} int GetY(){return Y;}}; void main() {Location retangleA={25,20,3,5,6,7,3};} private的数据成员不能采用这种方式初始化
例题分析 填上适当的字句,完成类中成员函数的定义 class A{ int *a; public: A(int aa=0){a=} //用aa初始化a所指向的动态对象 ~A(){;}};//释放动态存储空间 new int(aa); delete a; 填上适当的字句,完成类中成员函数的定义 class A{ ; int n; public: A(int nn=0):n(nn){} if(n==0) a=0; else a=new int[n]; //定义析构函数,释放动态数组空间 }; int *a; ~A(){delete[]a;}
例题分析 一个参数两个构造函数都可以调用,所以错 改错 class Time{ public: Time(int day) {iMonth=5; iDay=day; iYear=2000;} Time(int month,int day=7) {iMonth=month; iDay=day; iYear=2000;} private: int iMonth,iDay,iYear;}; void main() {Time input(29);}
例题分析 FoolDog():iD(7); 改错 class FoolDog{ public: FoolDog():iD=7; {} protected: int iD; };