析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统对象所分配的空间前,做一些善后工作。
析构函数也是类的成员函数,定义析构函数的格式为:
ClassName::~ClassName( )
{
… //函数体
}
例:为类定义析构函数。
#include<iostream.h>
class C
{ int i;
public:
C (){ i=0; cout<<"Constructor\n";}
void disp() { cout<<"i="<<i<<‘\n’;}
~C (){ cout<<"Destructor"<<endl; }
};
void main()
{ C a;
a.disp();
}//释放对象,调用析构函数
输出结果:
Constructor
i=0
Destructor
关于析构函数的几点说明:
1、析构函数是一个特殊的函数,它的名字与类名相同,并在前面加==“~”字符==,用来与构造函数加以区别。
析构函数不指定数据类型,并且也没有参数。
2、一个类中只可能定义一个析构函数。
3、析构函数是成员函数,函数体可写在 类体内,也可写在 类体外。
4、同 构造函数 一样,如果没有为类定义析构函数,系统会自动为类添加一个默认的析构函数,函数体为空。
5、析构函数可以被显式调用(不推荐),也可以系统调用。在下面两种情况下,析构函数会被自动调用。
- 如果一个对象是局部的,它具有块作用域,当对象所在的块结束时,该对象的析构函数被自动调用。
- 全局对象 和 静态对象 ,程序运行结束时,该对象的析构函数被自动调用。
6、当一个对象是使用new运算符被动态创建的,在使用delete运算符释放它时,delete将会 自动调用 析构函数。 如果不使用delete运算符释放,即使到了程序结束,也不会自动调用析构函数释放它。
例:复杂对象的构造函数和析构函数调用
class Sample
{ int x;
public:
Sample(int a=0) //构造函数
{ x=a;
cout<<"Constructore, x="<<x<<endl;
}
~Sample() //析构函数
{ cout<<"Destructor, x="<<x<<endl;}
void disp() //输出函数
{ cout<<"x="<<x<<endl;}
};
void fun(int i)
{ static Sample s2(i); //静态对象s2
Sample s3; //局部对象s3
s2.disp();
} //s3生命期结束
Sample s1; //全局对象s1,其x=0
void main()
{ Sample s4(50), *ptr=new Sample(100);
fun(10);
fun(20);
delete ptr; //释放动态对象
} //s1、s2、s4生命期结束
定义全局对象s1: Constructore, x=0
定义局部对象s4: Constructore, x=50
定义动态对象ptr: Constructore, x=100
定义静态对象s2: Constructore, x=10
定义局部对象s3: Constructore, x=0
输出对象s2: x=10
释放局部对象s3: Destructor, x=0
定义局部对象s3: Constructore, x=0
输出对象s2: x=10
释放局部对象s3: Destructor, x=0
释放动态对象ptr: Destructor, x=100
释放局部对象s4: Destructor, x=50
释放静态对象s2: Destructor, x=10
释放全局对象s1: Destructor, x=0
(先定义,先释放;后定义,后释放)
注意!
在程序的执行过程中,对象如果用 new运算符 开辟了空间,则在类中应该 自己定义一个析构函数,并在析构函数中 使用delete 删除由new分配的内存空间。
(下面是例子)
class Str{
char *Sp; int Length;
public:
Str(char *string)
{ if(string){ Length=strlen(string);
Sp=new char[Length+1];//申请动态内存,用成员数据指针指向
strcpy(Sp,string);//初始化动态空间
}
else Sp=0;
}
void Show(void){ cout<<Sp<<endl;}
~Str(){ if(Sp) delete [ ]Sp; }//释放对象时收回用new开辟的空间
};
void main(void)
{ Str s1("Study C++");
s1.Show();
}
- 使用构造函数可以实现类型转换。
例:使用构造函数实现强制类型转换。
#include<iostream.h>
class Point { int x,y;
public:
~Point() { cout<<"调用了析构函数!\n";}
Point(int a, int b)
{ x=a; y=b;
cout<<"x="<<x<<",y="<<y<<
"\t调用了构造函数!\n"; }
};
void main()
{ Point p1(5,10);
p1=Point(50,100);//创建临时对象、赋值,再释放
}
程序输出为:
x=5,y=10 调用了构造函数!
x=50,y=100 调用了构造函数!
调用了析构函数!
调用了析构函数!