C++_构造函数与析构函数
构造函数与析构函数
1 构造函数
1.1 构造函数具有⼀些特殊的性质
1.2 定义构造函数的⼀般形式
1.3 利⽤构造函数创建对象
2 成员初始化表
3 缺省参数的构造函数
4 重载构造函数
5 拷贝构造函数
5.1 ⾃定义拷贝构造函数
5.2 缺省的拷贝构造函数
5.3 调⽤拷贝构造函数的三种情况
5.4 浅拷贝和深拷贝
6 析构函数
7 调⽤构造函数和析构函数的顺序
8 对象的⽣存期
构造函数和析构函数都是类的成员函数,但它们都是特殊的成员函数,执⾏特殊的功能,不⽤调⽤便⾃动执⾏,⽽且这些函数的名字与类的名字有关。
C++语⾔中有⼀些成员函数性质是特殊的,这些成员函数负责对象的建⽴、删除。这些函数的特殊性在于可以由编译器⾃动地隐含调⽤,其中⼀些函数调⽤格式采⽤运算符函数重载的语法。
C++引进⼀个⾃动完成对象初始化过程的机制,这就是类的构造函数。
对象的初始化
1. 数据成员是不能在声明类时初始化
2. 类型对象的初始化⽅法:
构造函数可以被重载1. 调⽤对外接⼝(public成员函数)实现:声明类→定义对象→调⽤接⼝给成员赋值
2. 应⽤构造函数(constructor)实现:声明类→定义对象→同时给成员赋值
1. 构造函数
构造函数是⼀种特殊的成员函数,它主要⽤于为对象分配空间,进⾏初始化。
1.1 构造函数具有⼀些特殊的性质:
(1) 构造函数的名字必须与类名相同。
(2) 构造函数可以有任意类型的参数,但不能指定返回类型。它有隐含的返回值,该值由系统内部使⽤。
(3) 构造函数是特殊的成员函数,函数体可写在类体内,也可写在类体外。
(4) 构造函数可以重载,即⼀个类中可以定义多个参数个数或参数类型不同的构造函数。构造函数是不能继承
(5) 构造函数被声明为公有函数,但它不能像其他成员函数那样被显式地调⽤,它是在定义对象的同时被调⽤的。
(6) 在声明类时如果没有定义类的构造函数,编译系统就会在编译时⾃动⽣成⼀个默认形式的构造函数,
(7) 默认构造函数是构造对象时不提供参数的构造函数。
(8) 除了⽆参数构造函数是默认构造函数外,带有全部默认参数值的构造函数也是默认构造函数。
(9) ⾃动调⽤:构造函数在定义类对象时⾃动调⽤,不需⽤户调⽤,也不能被⽤户调⽤。在对象使⽤前调⽤。
(10) 调⽤顺序:在对象进⼊其作⽤域时(对象使⽤前)调⽤构造函数。
1.2 定义构造函数的⼀般形式
class 类名
{
public:
类名(形参表) ; //构造函数的原型
//类的其它成员
};
类名::类名(形参表) //构造函数的实现
{
//函数体
}
1.3 利⽤构造函数创建对象
(1) 利⽤构造函数直接创建对象.其⼀般形式为:类名对象名 (实参表);
这⾥的“类名”与构造函数名相同,“实参表”是为构造函数提供的实际参数。
例2.7 为类Date建⽴⼀个构造函数
#include <iostream.h>
class Date {
public:
Date(int y,int m,int d); // 构造函数
void setDate(int y,int m,int d);
void showDate();
private:
int year, month, day;
};
Date::Date(int y,int m,int d) // 构造函数的实现
{ year=y; month=m; day=d; }
void Date::setDate(int y,int m,int d)
{ year=y; month=m; day=d; }
inline void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
例2.8 利⽤构造函数直接创建对象
#include <iostream.h>
class Date {
// 省略,同例2.7
};
/
/ 省略,同例2.7
void main()
{
Date date1(1998,4,28); // 定义类Date的对象date1,
// ⾃动调⽤date1的构造函数,初始化对象date1
cout<<"Date1 output1:"<<endl;
date1.showDate(); // 调⽤date1的showDate(),显⽰date1的数据
date1.SetDate(2002,11,14); // 调⽤date1的setDate(),
// 重新设置date1的数据
cout<<"Date1 output2:"<<endl;
date1.showDate(); // 调⽤date1的showDate(),显⽰date1的数据
}
<
Date1 output1:
1998.4.28
Date1 output2:
2002.11.14
(2) 利⽤构造函数创建对象时,通过指针和new来实现。其⼀般语法形式为:
类名 *指针变量 = new 类名 (实参表);
void main()
{
Date *date1;
date1=new Date(1998,4,28);
//可合写成:Date *date1=new Date(1998,4,28);
cout<<"Date1 output1:"<<endl;
date1->showDate();
date1->setDate(2002,11,14);
cout<<"Date1 output2:"<<endl;
date1->showDate();
delete date1;
}
说明:
构造函数的名字必须与类名相同,否则编译器将把它当作⼀般的成员函数来处理。
构造函数是不能说明它的返回值类型的,甚⾄说明为void类型也不⾏。
构造函数可以是不带参数的。
class A{
public:
A();
//…
private:
int x;
};
A∷A()
{
cout<<"initialized \n";
x=50;
}
main()
{
…
}
例
有两个长⽅柱,其长、宽、⾼分别为:(1)12,25,30;(2)15,30,21。求它们的体积。要求:编⼀个基于对象的程序,在类中⽤带参数的构造函数。
class Box{
public:
Box(int,int,int);
int volume( );
private:
int height;
int width;
int length;
};
Box::Box(int h,int w,int len)
{
height = h;
width = w;
length = len;
}
int Box::volume( )
{
return height*width*length;
}
int main( )
{
Box box1(12,25,30);
cout << box1.volume( ) << endl;
Box box2(15,30,21);
cout << box2.volume( ) << endl;
return 0;
}
2. 成员初始化表
对于常量类型和引⽤类型的数据成员,不能在构造函数中⽤赋值语句直接赋值,C++提供初始化表进⾏置初值。
带有成员初始化表的构造函数的⼀般形式如下:
类名::构造函数名(参数表): (成员初始化表){ 构造函数体 }
成员初始化表的⼀般形式为:
数据成员名1(初始值1),数据成员名2(初始值2),……
例2.9 成员初始化表的使⽤
#include<iostream.h>
class A{
public:
A(int x1):x(x1),rx(x),pi(3.14) // rx(x)相当于rx=x, pi(3.14)相当于pi=3.14
{ }
void print()
{cout<<"x="<<x<<" "<<"rx="<<rx<<" "<<"pi="<<pi;}
private:
int x; int& rx; const float pi;
};
main()
{
A a(10);
a.print();
return 0;
}
构造函数采⽤成员初始化表对数据成员进⾏初始化,是⼀些程序员喜欢使⽤的⽅法。
class B{
int i;
char j;
float f;
public:
B(int I, char J, float F)
{ i=I; j=J; f=F; };
};
class B{
B(int I,char J,float F):i(I),j(J),f(F)
{ }
private:
int i;
char j;
float f;
};
说明
如果需要将数据成员存放在堆中或数组中,则应在构造函数中使⽤赋值语句,即使构造函数有成员初始化表也应如此。class C{
public:
C(int I,char Ch,float F,char N[]):i(I),ch(Ch),f(F)
{ strcpy (name,N);}
private:
int i;
char ch;
float f;
char name[25];
};
类成员是按照它们在类⾥被声明的顺序初始化的,与它们在初始化表中列出的顺序⽆关。
【例2.10】
#include<iostream.h>
class D {
public:
D(int i):mem2(i),mem1(mem2+1)
{
cout<<"mem1: "<<mem1<<endl;
cout<<"mem2: "<<mem2<<endl;
}
private:
int mem1;
int mem2;
};
void main()
{
D d(15);
}
mem1: -858993459
mem2: 15
3. 缺省参数的构造函数
例2.11
#include<iostream.h>
class Coord {
public:
Coord(int a=0,int b=0){ x=a; y=b;} // 带有缺省参数的构造函数
int getx(){ return x; }
int gety(){ return y; }
private:
int x,y;
};
void main()
{
Coord op1(5,6); Coord op2(5); Coord op3;
int i,j;
();();
cout<<"op1 i= "<<i<<" op1 j= "<<j<<endl;
();();
cout<<"op2 i= "<<i<<" op2 j= "<<j<<endl;
();();
cout<<"op3 i= "<<i<<" op3 j= "<<j<<endl;
}
class Box{
public:
Box(int h=10,int w=10,int l=10); //在声明构造函数时指定默认参数
int volume( ){ return(height*width*length); }
private:
int height;
int width;
int length;
};
Box:: Box(int h,int w,int l) //在定义函数时可以不指定默认参数
{
height=h;
width=w;
length=l;
}
4. 重载构造函数
构造函数的重载
在⼀个类中可以定义多个构造函数,以便对类对象提供不同的初始化的⽅法,供⽤户选⽤。这些构造函数具有相同的名字,⽽参数的个数或参数的类
型不相同(这称为构造函数的重载)
关于构造函数重载的说明
(1) 默认构造函数:⼀个调⽤构造函数时不必给出实参的构造函数。显然,⽆参的构造函数属于默认构造函数。⼀个类只能有⼀个默认
构造函数。
(2) 尽管在⼀个类中可以包含多个构造函数,但是对于每⼀个对象来说,建⽴对象时只执⾏其中⼀个构造函数,并⾮每个构造函数都被
执⾏。
class Box{
public:
Box(int h, int w, int l): height(h),width(w),length(l) { }
Box();
int volume( );
private:
int height;
int width;
int length;
};
Box::Box()
{
height = 10;
width = 10;
lenght = 10;
}
int Box::volume( )
{
return height*width*length;
}
int main( )
{
Box box1; // 书上为 box1();
cout << box1.volume( ) << endl;
Box box2(15,30,25);
cout << box2.volume( ) << endl;
return 0;
}
例2.17 重载构造函数应⽤例程。
#include <iostream.h>
class Date{
public:
Date(); // ⽆参数的构造函数
Date(int y,int m,int d); // 带有参数的构造函数
void showDate();
private:
int year, month, day;
};
Date::Date()
{ year=1998; month=4; day=28; }
Date::Date( int y, int m, int d)
{ year=y; month=m; day=d; }
inline void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
void main()
{
Date date1; // 声明类Date的对象date1,
// 调⽤⽆参数的构造函数
cout<<"Date1 output: "<<endl;
date1.showDate(); // 调⽤date1的showDate(),显⽰date1的数据
Date date2(2002, 11, 14); // 定义类Date的对象date2,
// 调⽤带参数的构造函数
cout<<"Date2 output: "<<endl;
date2.showDate(); // 调⽤date2的showDate(),显⽰date2的数据
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论