C++ 类的默认成员函数-构造函数
个人主页:Jason_from_China-CSDN博客
所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客
所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客
概念概述
- 默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。一个类,我们不写的情况下编译器会默认生成以下 6 个默认成员函数,需要注意的是这 6 个中最重要的是前 4 个,最后两个取地址重载不重要,我们稍微了解一下即可。其次就是 C++11 以后还会增加两个默认成员函数,移动构造和移动赋值,这个我们后面再讲解。默认成员函数很重要,也比较复杂,我们要从两个方面去学习。
包括
构造函数
概念概述
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象 (我们常使用的局部对象是栈帧创建时,空间就开好了),而是对象实例化时初始化对象。构造函数的本质是要替代我们以前 Stack 和 Date 类中写的 Init 函数的功能,构造函数自动调用的特点就完美的替代的了 Init。
构造函数的特点:
- 函数名与类名相同。
- 无返回值。(返回值啥都不需要给,也不需要写 void,不要纠结,C++ 规定如此)
- 对象实例化时系统会自动调用对应的构造函数。
- 构造函数可以重载(因为需要不同的数据,不同的初始化,会使开发更加简单)。
- 如果类中没有显式定义构造函数,则 C++ 编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
- 无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个函数有且只有一个存在,不能同时存在。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认生成那个叫默认构造,实际上无参构造函数、全缺省构造函数也是默认构造,总结一下就是不传实参就可以调用的构造就叫默认构造。
- 我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,看编译器。对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要用初始化列表才能解决,初始化列表,我们下个章节再细细讲解。
- 简单的说构造函数就是用来初始化的函数,而且默认构造函数会自动调用
注意:
C++ 把类型分成内置类型 (基本类型) 和自定义类型。内置类型就是语言提供的原生数据类型,如:int/char/double/ 指针等,自定义类型就是我们使用 class/struct 等关键字自己定义的类型。
构造函数的实现
不带参数构造函数
//.h///默认构造函数的使用 class MyClass { public://默认构造函数MyClass()//类名相同,没有参数,叫做无参数构造函数{_year = 1999;_month = 12;_day = 1;cout << "默认构造函数的自动调用:" ;cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day; };//.cpp int main() {MyClass d1;return 0; }
此时我们发现这里在初始化的时候自动调用无参数构造函数(也就是默认构造函数),当然这里初始化成功
带参数构造函数
//.h class MyClass1 { public:MyClass1(int year, int month, int day){_year = year;_month = month;_day = day;cout << "带参数构造函数的调用:";cout << _year << "/" << _month << "/" << _day << endl << endl;}private:int _year;int _month;int _day; };//.cpp int main() {//不带参数构造函数MyClass d1;//带参数构造函数MyClass1 d2(2024, 9, 14);//带参构造函数这里是需要传递一个参数return 0; }
半缺省构造函数
//.h //半缺省构造函数(从右往左进行赋值) class MyClass2 { public:MyClass2(int year, int month, int day = 28){_year = year;_month = month;_day = day;cout << "半缺省构造函数(从右往左进行赋值):";cout << _year << "/" << _month << "/" << _day << endl << endl;}private://私有变量,只能类里面的函数进行访问int _year;int _month;int _day; };//.cpp int main() {//不带参数构造函数MyClass d1;//带参数构造函数MyClass1 d2(2024, 9, 14);//半缺省构造函数(从右往左进行赋值),赋值的时候,从左往右哦,就是为了和构造函数的缺省参数进行分开MyClass2 d3(2000, 2);return 0; }
半缺省构造参数(从右往左进行赋值),赋值的时候,从左往右哦,就是为了和构造函数的缺省参数进行分开
全缺省构造函数
//全缺省构造函数(从右往左进行赋值) class MyClass2 { public:MyClass2(int year, int month, int day = 28){_year = year;_month = month;_day = day;cout << "半缺省构造参数(从右往左进行赋值):";cout << _year << "/" << _month << "/" << _day << endl << endl;}private://私有变量,只能类里面的函数进行访问int _year;int _month;int _day; };int main() {//不带参数构造函数MyClass d1;//带参数构造函数MyClass1 d2(2024, 9, 14);//半缺省构造函数(从右往左进行赋值)MyClass2 d3(2000, 2);//全缺省构造函数MyClass3 d4;return 0; }
默认构造函数
无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个函数有且只有一个存在,不能同时存在。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认生成那个叫默认构造,实际上无参构造函数、全缺省构造函数也是默认构造,总结一下就是不传实参就可以调用的构造就叫默认构造。
总结:
简单的说就是,在创建对象初始化的时候,会自动调用的函数,带参数构造函数不是默认构造函数,是需要调用的时候传参的。默认构造函数在调用创建对象的时候是不需要传参的。上面我们的代码很清晰了。
构造函数注意事项
对于自定义类型来说,构造函数往往是需要自己实现的。因为自定义类型的初始化可能较为复杂,需要根据特定的逻辑来进行成员变量的初始化等操作。例如,一个包含多个成员变量且有特定初始化需求的自定义类,通常需要定义构造函数来确保对象在创建时被正确初始化。
对于内置类型来说是不需要的。内置类型如 int、char、double 等,在创建对象时如果不进行显式初始化,它们会被自动赋予默认值(对于数值类型通常为 0,对于指针类型通常为 nullptr 等)。当然,如果需要特定的初始值,也可以在定义变量时进行显式初始化,但一般情况下不需要专门为内置类型定义构造函数。