@[toc]
默认成员函数
首先要理解什么是默认成员函数:类在什么都不写的时,编译器会生成六个默认成员函数
用户没有显式实现,但编译器会生成的成员函数就是默认成员函数
下面我们对这些函数一一进行介绍
构造函数
在C语言中,无论是实现栈队列链表等各种数据结构,都避免不了要写Init初始化函数,这个函数的功能是给变量一个初始化的值,在C++中,认为C语言的这些问题有些许麻烦,于是进行了一定的优化,构造函数就是要在对象创建的时候,就把信息设置进去
构造函数是一个特殊的成员函数,名字和类名相同,创建类型对象的时候就由编译器自己自动调用,用来保证类中的每一个数据成员都有一个自己的初始值,在整个对象的生命周期中只调用一次
构造函数的特性
构造函数是特殊的成员函数,主要功能是用来初始化对象
它有下面的一些特点
- 函数名和类名相同
- 没有返回值
- 对象实例化的时候会自动调用对应的构造函数
- 构造函数可以重载
- 如果类中没有显式的构造函数,那么会自动生成一个无参的默认构造函数,如果用户定义了构造函数就不再生成
- 默认构造函数是在不写的时候会生成,且内置类型的成员不会进行处理(在C++11中的声明支持给缺省值),自定义类型的成员才会处理,回去调用这个成员的默认构造函数
- 无参的构造函数和全缺省的构造函数都是默认构造函数,这两个构造函数只能存在一个
既然它有这么多的特点,那么就一一举例论证它的特点
==1. 函数名和类名相同
- 没有返回值
- 对象实例化的时候会自动调用对应的构造函数
- 构造函数可以重载==
在实际写代码时,尽量要写全缺省的构造函数,这样不管如何给参数都有一定的初始化值
class Date
{
public:
Date(int year=1, int month=1, int day=1)
{
cout << "Date(int year, int month, int day)" << endl;
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(2004);
Date d3(2004, 6);
Date d4(2004,6,16);
return 0;
}
==5. 如果类中没有显式定义构造函数,则编译器会自动生成一个无参的默认构造函数,一旦用户有显式定义就不再生成==
这里也是我们接触到的第一个默认构造函数,我们用下面的代码证明它的存在性
下面继续验证它的后半段存在性
从中可以看出,当我们没有定义构造函数时,定义一个无参的对象编译器会执行默认构造函数给数据成员初始值,而现在我们定义了构造函数,那么默认构造函数不复存在,此时编译器也就不能执行默认构造函数给无参的d1初始化值,此时会报错---Date不存在默认构造函数,没有合适的构造函数可以使用
==6. 默认构造函数是在不写的时候会生成,内置类型的成员不会进行处理(在C++11中的声明支持给缺省值),自定义类型的成员才会处理,回去调用这个成员的默认构造函数==
简单来说,一般情况下都需要我们自己写构造函数,决定初始化方式,成员变量都是自定义类型,可以考虑不写构造函数,因为会调用自定义类型的构造函数
==7. 无参的构造函数和全缺省的构造函数都是默认构造函数,这两个构造函数只能存在一个==
后续还有初始化列表,我们后续进行讲解
析构函数
析构函数就相对简单一点
它存在的意义是什么呢?
我们实现栈顺序表链表等数据结构时,都要在堆上malloc开辟一段空间,但是是不是经常会忘记free呢?这样会造成内存泄漏的危险情况的发生
那么C++在开发的时候就想到了这个问题,因此析构函数就这样产生了,它存在的意义就是完成对象中资源的清理工作,它会在对象被销毁前自动调用
析构函数的特点如下
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。析构函数不能重载
- 对象生命周期结束时,C++编译自动调用析构函数。
- 调用顺序满足栈的顺序