说起默认成员函数,每一个C++程序员都不会陌生,因为默认成员函数就如同是一栋大厦的地基。我们常说“基础不牢,地动山摇”,在这里得到充分的体现。本章介绍两种默认成员函数:构造函数和析构函数。
正文开始~~~
构造函数
相信每一个C++程序员都是从C语言走过来的,而C++作为比C更先进的语言,肯定要修改一下C语言不好的地方。比如:用C语言实现栈、队列等数据结构的时候每次都需要先对其进行初始化,但是我们程序员都是人,不是机器,肯定会有忘记的时候,忘记初始化的后果不用我多说。所以我们C++的祖师爷本贾尼博士(Bjarne Stroustrup)也是深受其扰,然后就提出了构造函数的概念,在对象被创建时,构造函数被自动执行。
构造函数的特性
具体每条特性我会根据代码一一介绍:
- 函数名与类名相同。
- 无返回值。
- 对象实例化时编译器自动调用对应的构造函数。
//一个日期类
class Date
{
public://构造函数名与类名相同,并且无返回值Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "_" << _month << "_" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{//对象实例化,自动调用构造函数Date d1(2024,4,11);d1.Print();//结果为:2024_4_11 注:VS2022测试return 0;
}
4.构造函数可以重载。
//上面代码的构造函数还可以写成这种形式
Date(int year = 1, int month = 1, int day = 1)
{_year = year;_month = month;_day = day;
}
5.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
//还是上面的代码,但是我们没有主动显示的写构造函数
class Date
{
public://下面的两行代码就相当于编译器自动生成的构造函数//Date()//{}void Print(){cout << _year << "_" << _month << "_" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{//对象实例化,自动调用构造函数Date d1;d1.Print();//结果为:随机值_随机值_随机值 注:VS2022测试return 0;
}
6.C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型。编译器生成的默认成员函数对于内置类型C++没有规定要不要处理,具体看编译器,而对于自定义类型会默认调用自定义类型的默认成员函数。
//在上述代码的基础上,我们又添加了一个Time类(自定义类型)
class Time
{
public://Time的构造函数,因为这是我们主动写的,所以编译器不会自动生成Time(){_hour = 0;_minute = 0;_second = 0;}void Print(){cout << _hour << "_" << _minute << "_" << _second << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
public:void Print(){cout << _year << "_" << _month << "_" << _day << endl;}
private:int _year;//内置类型,C++没有规定要不要处理,看编译器int _month;int _day;Time _t;//自定义类型,调用自定义类型的默认构造函数
};int main()
{Date d1;d1.Print();//结果为:随机值_随机值_随机值 注:VS2022测试Time t1;t1.Print();//结果为:0_0_0 注:VS2022测试return 0;
}
7.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器自动生成的构造函数,都可以认为是默认构造函数。
构造函数总结
- 一般情况下构造函数都需要我们自己显示的去实现
- 只有少数情况下可以让编译器自动生成构造函数
析构函数
与构造函数一样,有初始化,就会有销毁,而析构函数的作用就是完成对象中资源的清理工作,所谓的资源清理工作就是,malloc了不用free;fopen了不用fclose等等,后续的工作析构函数会自动调用帮你完成。怎么样?是不是爽得很hhhhh
析构函数的特性
具体每条特性我会根据代码一一介绍:
1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值类型。
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
typedef int DataType;
class Stack
{
public://自己写的构造函数Stack(size_t capacity = 4){_array = (DataType*)malloc(sizeof(DataType) * capacity);_capacity = capacity;_size = 0;}// 析构函数无参数无返回值,函数名是在类名前面加上~~Stack(){cout << "~Stack()" << endl;if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};int main()
{//对象实例化Stack st;//结果为:~Stack()。从结果我们可以看出自动调用了析构函数return 0;
}
5. 编译器自动生成的默认析构函数,对自定类型成员调用它的析构函数。
class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:int _year; // 基本类型(内置类型)int _month;int _day;Time _t; // 自定义类型//我们没显示写析构函数,编译器自动生成析构函数,//然后去调用自定义类型的析构函数,这里跟构造函数是一样的
};
int main()
{Date d;//结果为:~Time()return 0;
}
6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
析构函数总结
1. 有资源需要显示清理,就需要写析构函数,如:Stack。
2. 有两种场景不需要显示写析构函数,默认生成就可以。
a.没有资源需要清理,如:Date。
b.内置类型成员没有资源需要清理,如:MyQueue。