目录
(一)构造函数可以被重载,C++根据声明中的参数选择合适的构造函数。
(二)还可以通过给构造函数以参数默认值,使上面四个构造函数合成一个。
一、析构函数的必要性
一个类可能在构造函数里分配资源,这些资源需要在对象不复存在以前被释放。例如,如果构造函数打开了一个文件,文件就需要被关闭。 或者,如果构造函数从堆中分配了内存,这块内存在对象消失之前必 须被释放。析构函数允许类自动完成这些清理工作,不必调用其它成员函数。
析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命期结束的时候,由系统自动调用。
作为一个类,可能有许多对象,每当对象生命期结束时,都要调用析构函数,每个对象一次。这跟构造函数形成了鲜明的对立,所以析构函数名,就在构造函数名前加一个逻辑非运算符“~”,表示“逆构造函数。”,看下面这个例子,定义了一个析构函数:
class XYZ
{
public:
XYZ()
{
name=new char[20]; //分配堆空间
}
~XYZ()
{
delete name; //释放堆空间
}
protected:
char *name;
}
二、调用顺序如何?
析构函数以调用构造函数相反的顺序被调用。
三、带参数的构造函数
构造函数可以带参数,带参数的构造函数使初始化一步到位。
(一)带一个参数
举个栗子:
#include <iostream.h>
#include <string.h>
class Student
{
public:
Student(char *pName)
{
cout<<"constructing student "<<pName<<endl;
strncpy(name,pName,sizeof(name));
name[sizeof(name)-1]='\0';
}
~Student()
{
cout<<"destructing student.\n";
}
//其它公共成员函数
protected:
char name[20];
};
void main()
{
Student ss("Jenny");
//...
}
(二)带多个参数
举个栗子:
#include <iostream>
using namespace std;
class Student
{
public:
Student(string Name, int xHours, float xgpa)
{
cout << "constructing student " << Name << endl;
name = Name;
semesHours = xHours;
gpa = xgpa;
}
~Student()
{
cout << "destructing student.\n";
}
protected:
string name;
int semesHours;
float gpa;
};
int main()
{
Student ss("Jenny", 22, 3.5);
//...
return 0;
}
四、重载构造函数
(一)构造函数可以被重载,C++根据声明中的参数选择合适的构造函数。
举个栗子:
#include <iostream>
using namespace std;
class Date
{
public:
Date();
Date(int d);
Date(int m, int d);
Date(int m, int d, int y);
//其它公共成员函数
protected:
int month;
int day;
int year;
};
Date::Date()
{
month=4; day=15; year=1995;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int d)
{
month=4; day=d; year=1996;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int m, int d)
{
month=m;
day=d;
year=1997;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int m, int d, int y)
{
month=m;
day=d;
year=y;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
void main()
{
Date aday;
Date bday(10);
Date cday(2,12);
Date dday(1,2,1998);
}
(二)还可以通过给构造函数以参数默认值,使上面四个构造函数合成一个。
class Date
{
public:
Date(int m=4, int d=15, int y=1995)
{
month=m; day=d; year=y;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
};
Date::Date()
{
month=4; day=15; year=1995;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int d)
{
month=4; day=d; year=1996;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int m, int d)
{
month=m;
day=d;
year=1997;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
Date::Date(int m, int d, int y)
{
month=m;
day=d;
year=y;
cout<<month<<"/"<<day<<"/"<<year<<endl;
}
构造函数参数默认规则与其它函数参数默认规则相同,如上面的构造函数,可以默认年、默认日与年、也默认日、 月、年都默认,其它条件不允许默认。重载构造函数若与参数默认值的构造函数发生冲突, 则创建对象的语句会导致编译错误。举个栗子:
五、默认构造函数
(1)C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
(2)若未提供一个类的构造函数(一个都未提供),则C++提供一个默认的构造函数,该默认构造函数是个无参构造函数,它仅负责创建对象,而不做任何初始化工作。
(3)只要一个类定义了一个构造函数(不一定是无参构造函数),C++ 就不再提供默认的构造函数。也就是说,如果为类定义了一个带参数的构造函数,还想要无参构造函数,则必须自己定义。
(4)与变量定义类似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象值是随机的。
看个栗子,下面的代码在创建对象时,将自动调用系统提供的默认构造函数: