1.构造函数
构造函数是特殊的成员函数
创建类类型的新对象时,系统会自动调用构造函数
构造函数是为了保证对象的每个数据成员都被正确初始化
①构造函数的特点
函数名和类名完全相同
不能定义构造函数的类型(返回类型),也不能使用void
通常情况下构造函数应声明为公有函数,否则它不能向其他函数那样显式地调用
构造函数被声明为私有时有特殊的用途
②默认构造函数:不带参数的构造函数
如果程序中未声明构造函数,则系统自动产生出一个默认构造函数(如果程序中已经定义了构造函数,则系统不会自动生成默认构造函数,需要手动编写)
③构造函数的重载
一个类中可以有多个构造函数,编译器会自动重载
④构造函数与new运算符
定义指针对象时要使用new在堆上进行分配
④全局对象的构造函数先于main函数
2.析构函数
析构函数是程序结束时,系统自动调用用于释放空间的
析构函数的函数名和类名相似(前面多了一个字符“~”)
析构函数没有返回类型,也没有参数
析构函数不能被重载
如果没有定义析构函数,编译器会自动生成一个默认析构函数
析构函数是一个空函数
①析构函数与数组
如果想要析构函数释放数组,必须先用delete释放数组空间
②析构函数与delete运算符
Delete运算符会引起析构函数的调用
③析构函数的显式调用
除了系统自动调用,我们也可以在程序中显式的调用析构函数
注意:析构的顺序与构造的顺序相反
下面用一个例子来综合理解上面的几点
首先,编写一个Test.h,用于声明类
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test();
Test(int x, int y, int z);
~Test();
private:
int x_;
int y_;
int z_;
protected:
};
#endif
接着,编写Test.cpp来外部实现构造函数以及析构函数,我们在构造函数和析构函数中增加了一些打印信息,以此来观察构造和析构的顺序
#include "Test.h"
#include <iostream>
using namespace std;
Test::Test()
{
cout << "Default Init" << endl;
}
Test::Test(int x, int y, int z)
{
x_ = x;
y_ = y;
z_ = z;
cout << "Init x = " << x_ << endl;
}
Test::~Test()
{
cout << "Destroy x = " << x_ << endl;
}
最后,编写main函数,我们在其中定义了两个对象,一个指针对象,还有一个数组对象,指针必须使用new进行分配,使用delete进行释放
#include "Test.h"
#include <iostream>
int main()
{
Test t1(1,2,3);
Test t2;
Test *p = new Test(4,5,6);
Test array[3];
delete p;
return 0;
}
现在我们来看一下结果,可以看到构造和析构的顺序,发现指针对象的析构先于数组,这是因为调用了delete释放指针,delete引起了析构函数的调用,所以先对指针进行了析构,之后按照正常顺序进行析构