1. 构造函数
程序中常需要对变量赋初值进行初始化,这在基于过程的程序中是很容易的,在定义变量时赋以初值,比如: int a = 10;
而在基于对象的设计中,在定义一个对象时,也需要做初始化的工作,即对成员变量赋初值进行初始化。对象代表一个实体,每一个对象都有它确定的属性(成员变量),在系统为对象分配内存时,应该对有关的数据成员初始化。
-如果一个类的所有成员变量都是公有的,则可以在定义对象时对成员变量直接进行初始化,比如:
class Time
{
public:
int _hour;
int _minute;
int _sec;
};
Time t={12,0,0};//定义对象时直接进行初始化
-如果成员变量是私有的,或者类中有private或protected的成员变量,则不能用上述方法,这就用到了构造函数。
C++提供了一个公有成员函数-构造函数来处理对象的初始化。构造函数与其它公有函数不同,不需要用户调用它,仅在定义对象时自动执行一次。构造函数的特点有以下几个方面:
- 函数名必须与类名相同
- 构造函数无返回值
- 对象构造时(对象实例化)时自动调用构造函数
- 构造函数可以重载
- 构造函数可以在类内定义,也可以在类外定义(类外定义需加::)
- 构造函数无隐含的this形参
- 如果用户没有定义构造函数,则编译器会自动生成一个无参的构造函数
- 无参的构造函数和全缺省值的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个
- 构造函数写成全缺省的方式最好
class Time
{
private:
int _hour;
int _minute;
int _sec;
public:
Time();//无参的构造函数
Time(int hour=12,int minute=0,int sec=0);//全缺省的构造函数,采用类外定义方式
};
Time::Time(int hour=12,int minute=0,int sec=0)
{
_hour=hour;
_minute=minute;
_sec=sec;
}
void TestTime()
{
Time t1;//调用无参的构造函数
Time t2(24,0,0);//调用全缺省的构造函数
}
2. 拷贝构造函数
-拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。那么什么时候拷贝构造函数会被调用呢,有以下情况:
-对象以值传递的方式传入函数体
-对象以值传递的方式从函数返回
-对象需要通过另一个对象进行初始化
拷贝构造函数的特点有以下几个方面:
- 拷贝构造函数其实是一个构造函数的重载
- 拷贝构造函数的参数必须是引用传参
- 如果用户没有定义拷贝构造函数,系统会默认生成一个缺省的拷贝构造函数。缺省的拷贝构造函数会,依次拷贝类成员进行初始化。
class Time
{
private:
int _hour;
int _minute;
int _sec;
public:
Time();
Time(Time& t); //拷贝构造函数
{
_hour=t->_hour;
_minute=t->_minute;
_sec=t->_sec;
}
};
void Test()
{
Time t1;//调用构造函数
Time t2(t1);//用t1初始化t2,调用拷贝构造函数
}
3. 析构函数
析构函数与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统会自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
析构函数也是特殊的成员函数,特点有:
- 析构函数在类名前加~
- 析构函数无返回值无参数,所以析构函数不能重载
- 一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。
- 对象的生命周期结束时,编译器会自动调用析构函数
- 析构函数并不是删除对象,而是“清理善后”,比如new空间的释放
- 先构造的对象后析构
class Time
{
private:
int _hour;
int _minute;
int _sec;
public:
Time(int, int, int);//全缺省构造函数
Time(Time& t);//拷贝构造函数
~Time();//析构函数
};
Time::Time(int hour = 24, int minute = 0, int sec = 0)
{
_hour = hour;
_minute = minute;
_sec = sec;
cout << "调用了构造函数" << endl;
}
Time::Time(Time& t)
{
_hour = t._hour;
_minute = t._minute;
_sec = t._sec;
cout << "调用了拷贝构造函数" << endl;
}
Time::~Time()
{
cout << "调用了析构函数" << endl;
}
int main()
{
{
Time t1;
Time t2(t1);
}
//在对象生命周期结束后,编译器会自动调用析构函数,先构造的后析构,所以花括号内是对象的生命周期。
}