目录
☃️一.理解默认成员函数
不知大家在学习C语言的时候会不会忘记写函数的初始化和函数的销毁,在我学习的过程中,这两个也是经常忘记的。在C++设计中,大佬们应该也考虑了这个问题,因此将初始化和销毁等等一些函数改成默认的了,当我们不写时编译器自动生成这些函数,我们将编译器生成的默认函数称为默认成员函数。
☃️二.构造函数的理解
作用:构造函数主要完成初始化工作。
特性:
①函数名与类名相同
②无返回值
③对象实例化时自动调用对应的构造函数
④构造函数可重载
实例:
假如我们实现一个日期类
//日期类
class Date
{
public:
private:
int _year;
int _month;
int _day;
};
根据构造特性①②那么它的构造函数如下
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
我们实例化一个对象并传参(传参在创建对象的后面传参)
int main()
{
//创建对象并传参
//创建完对象后自动去调用我们写的构造函数
Date d1(2001, 10, 29);
return 0;
}
在传参过程中,不能写成如下形式
/错误示范 int main() { Date d1(); return 0; }
原因:
存在混淆,不知道是在函数声明,还是定义对象传无参
构造函数也支持重载,重载函数可以写成以下形式
//构造函数的重载形式
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
//它的重载函数其实可以本身的构造函数结合如下:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//如写了这种形式的话,那么无参的和全缺省的二者只能存在一个
//不然会调用的二义性
我们知道构造函数如果在类中无定义的话,那么它会自动生成无参的构造函数,如果我们写了构造函数,那么编译器也不会生成。那我们不妨用上面的日期类看看生成的构造函数能否完成初始化工作
结论:
构造函数对内置类型不进行处理
补充:
内置类型:如 int、double、float等等
我们来写一个自定义类型的队列
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int) * capacity);
if (_a == nullptr)
{
perror("malloc fail");
exit(-1);
}
_top = 0;
_capacity = capacity;
}
private:
int* _a;
int _top;
int _capacity;
};
class MyQueue
{
public:
private:
//只有自定义类型的时候
Stack _pushST;
Stack _popST;
};
此时我们的队列并没有写构造函数,看看它默认生成的构造函数可不可以满足我们的需求
观察以上结果,我们的队列并没有写构造函数,而它却完成了初始化。这是因为为们的栈写了存在构造函数,如果类中的自定义变量有构造函数,那么我们可以不写构造函数
结论:
面向需求写构造函数,如果编译器默认生成的构造函数可以满足我们的需求我们就不写构造函数,如果默认生成的构造函数不满足我们的要求,那么我们就要去写一个构造函数。
补充:
默认构造函数:无参和全缺省或者编译器自动生成的成员函数叫做默认构造函数。
☃️三.析构函数
作用:完成对象的资源清理工作
特性:
①析构函数名在类名前加上~
②无参数无返回值
③一个类只有一个析构函数,系统会自动生成默认的析构函数(析构函数不能重载)
④对象生命周期结束时,编译器自动调用析构函数
补充:
先定义的后析构,后定义的先析构
根据析构函数特性写析构函数如下
~Stack()
{
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
析构函数函数作用后如下:
补充:
生命周期:
局部变量 -> 函数调用结束结束
全局变量 -> main函数结束
malloc -> 手动free
结论:
有资源需要释放也不一定需要自己写析构函数,像我们上述中的MyQueue就不用写析构函数,因为默认生成的够用。总而言之:面向需求写析构函数,如果默认生成的够用就不用写析构函数,不够用就写。
☃️四.总结
无论是对于构造函数还是析构函数,它们有着相同的特性,对内置类型不处理,而构造函数的需要给内置类型写构造函数去完成初始化工作,而析构函数不对内置类型不进行处理,它一般去清理需要资源清理的,像我们malloc的空间; 而对于自定义类型看需求写构造函数,如果默认生成的构造函数不满足我们的初始化工作,那么我们就需要自己写一个构造函数来完成初始化。析构函数同理。