目录
一、类的默认成员函数
1、背景
在用 C 写代码时,常常会忘记初始化和释放空间。对此,C++为了避免我们犯下这种低级错误,于是发明了下面这6种成员函数,在使用时会自动调用。
2、什么是默认成员函数
默认成员函数,其实就是当我们不写这类函数的实现时,编译器会自动帮我们生成一个,但当我们写了这类函数后,编译器就不会生成了。这类函数就是默认成员函数,他们分别是构造函数、拷贝构造函数、析构函数、赋值重载函数、取地址重载函数和 const 取地址重载函数。
二、构造函数(Constructor)
1、什么是构造函数?
构造函数(constructor),顾名思义就是负责初始化类实例化变量的数据的函数。它是 C++ 6大默认成员函数之一,因此从你把类实例化时, 编译器就会自动把这个实例化进行初始化,防止你忘了。
2、构造函数的格式
(1)函数名要和类名一样
(2)函数没有返回值,且返回类型也不用写 void
(3)构造函数支持函数重载
(4)函数域里面就按普通函数写就行了
class Date
{
public:
/*构造函数(无参)*/
Date()
{
}
/*构造函数(带参)*/
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
return 0;
}
但是,需要注意的是:虽然语法上构造函数支持函数重载,但就像上图的例子,当我们像上图那样把 Date 实例化后,由于无参的构造函数和全缺省构造函数同时存在,因此无论是哪个函数,都可以进行无参调用,因此编译器就不知道你到底要调哪个了。
因此,在一个类中,全缺省构造函数、无参构造函数、编译器自带的构造函数这三个函数只能存在一个,互不相容。
3、构造函数的调用规则
(1)如何调用构造函数?(以上面的Date为例)
1.1 无参函数
int main()
{
Date d1;
return 0;
}
不用在 d1后面加括号
1.2 缺省函数
1.2.1 全缺省函数
Date d1;
//or
Date d2(2023, 4, 23);
1.2.2 部分缺省函数
Date d3(2023, , 23);
1.3 普通函数
Date d1(2026, 4,15);
(2)默认构造函数(重点)
2.1 什么是默认构造函数?
当实例化的变量在初始化时可以不用传实参,那么这个构造函数就是默认构造函数。就如全缺省构造函数、无参函数、编译器自带的构造函数。
2.2 编译器自带的构造函数的特征
编译器自带的构造函数只会对自定义类型(如 class、struct、union等等)调用它(自定义类型)自己的构造函数,但不会对内置类型(如 int、char、double、指针等)进行初始化操作。
因此,我们可以在 private 里对每个变量给上缺省值(C++11的补丁)
class Date
{
int _year = 1;
int _month = 1;
int _day = 1;
};
2.3 默认构造函数使用条件(重点)
因此除非整个类里的成员都是自定义类型,否则不要调用默认构造函数。
三、析构函数(Destructor)
1、什么是析构函数?
析构函数(Destructor),顾名思义,就是负责把对象的数据清除的函数。
2、析构函数的格式
除了要在函数名前加上 ~ 之外,其余部分的格式和构造函数的一样。
3、析构函数调用规则
(1)何时调用?
析构函数会在对象生命周期结束时自动调用。
(2)调用哪个析构?
如果显式定义了析构函数,那么程序就不会自己生成默认析构函数;反之,如果没有显式定义析构函数,程序就会自动生成一个默认析构函数。而这个默认析构函数不会处理内置类型;如果遇到自定义类型就会调用这个自定义类型它自己的析构函数。
因此,当一个对象里面的都是不用清除的数据或都是自定义类型时,我们就不用显式定义我们的析构函数了。但如果构造函数中有开在堆上的空间,那么我们就要自己写析构函数了。