网站建设系统,建设免费网站,长沙网站设计我选刻,wordpress 上传svg回顾知识 在学习类的默认成员函数之前#xff0c;先带大家复习一下什么是类#xff0c;类是在C中引进的新的类型#xff0c;是一种自定义类型#xff0c;实际上跟C语言中的结构体类似#xff0c;但是是对结构体的升级#xff0c;可以在类里面添加函数#xff0c;也有对应…回顾知识 在学习类的默认成员函数之前先带大家复习一下什么是类类是在C中引进的新的类型是一种自定义类型实际上跟C语言中的结构体类似但是是对结构体的升级可以在类里面添加函数也有对应的访问限定符privatepublic和protect在C中依旧可以使用结构体struct因为C要兼容C只不过我们可以直接使用类名来实例化对象还有一点就是class在不写访问限定符的时候默认为private私有而struct不写默认的是public这也跟C要兼容C有关因为我们在C语言中struct的成员都是可以直接访问的。 一、 为什么要引入构造函数 其实我们在实现一个日期类的时候我们肯定是需求在实例化对象的时候就初始化好我们的日期比如2023年11月20日 在没有学习构造函数之前我们会怎么把日期传给我们的成员变量呢来看下面的代码 #include iostream
using namespace std;
class Date
{
public:void Init(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 date;date.Init(2023, 11, 20);date.Print();return 0;
}所以我们在不知道构造函数的存在之前我们只会这样初始化日期其实准确来说并不是初始化我们只是简单的赋值而真正的初始化是在初始化列表中实现的因为初始化列表只能允许成员变量出现一次所以也就赋值一次这才是初始化我们回到正题如果每次写类的时候都要这样实现初始化神都会觉得麻烦基于这样的理念我们的构造函数就诞生了 二、 什么是构造函数 构造函数是一种特殊的成员函数跟我们之前所有的函数模样都不一样。 构造函数不用写返回值构造函数的函数名是类名构造函数允许重载构造函数是在实例化对象时自动调用的构造函数的参数可以给缺省值 下面就是构造函数的写法
class Date
{
public:Date(int year, int month, int day){_year year;_month month;_day day;}
private:int _year;int _month;int _day;
};上面就是构造函数的一种简单的写法构造函数就是用来给成员变量赋值的记住是赋值不是初始化构造函数体内可以进行多次赋值这跟初始化的概念截然不同在后面讲的初始化列表才是初始化还有一点就是我们显式地去写了构造函数编译器就不会生成了这也就是说明了默认成员函数是编译器自己会生成的。既然我们可以写构造函数编译器可以生成构造函数那构造函数的分类是什么呢 三、 构造函数分为哪几种 构造函数分为下面两类 显式构造函数必须传参的如半缺省无缺省默认构造函数不需要传参的如全缺省无参和编译器默认生成的 注意事项: 默认构造函数只允许存在一个写了显式构造函数编译器就不会生成默认构造函数对于自定义类型的成员变量当前类的构造函数会调用这个自定义类型的默认构造函数如果这个自定义类型没有默认构造就会报错 四、 什么是初始化列表 其实最常用的并不是构造函数而是我们的初始化列表它的存在解决了对于必须在定义的时候初始化的变量和一些没有默认构造函数的自定义类型。 使用规则冒号开头逗号接应末尾没有分号
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};注意事项 C11 中针对内置类型成员不初始化的缺陷又打了补丁。即内置类型成员变量在类中声明时可以给默认值其实就是给的初始化列表。成员变量在类中声明次序就是其在初始化列表中的初始化顺序与其在初始化列表中的先后次序无关 五、 对构造函数的提问
1. 为什么要自己写构造函数 给大家举两个例子 第一个是在日期类编译器生成的默认构造函数是没办法给我们的日期正常赋值的会赋值但是是给随机值所以不满足我们的需求我们会写构造函数给正确的值第二个是栈顺序表链表二叉树等需要申请资源开辟空间的我们的编译器生成的默认构造函数是没办法进行malloc和realloc等操作的所以我们要自己写一个构造函数来开辟空间综上所述我们写构造函数的原因就是基于编译器生成的默认构造函数没办法提供我们正常的需求。 2. 对于成员变量是自定义类型我们如何构造 大家在这里要知道凡是类里面有自定义类型无论是默认构造函数还是显式构造函数都会调用这个自定义类型自己的默认构造函数。如果这个自定义类型没有默认构造函数编译器会报错。 3. 初始化列表和构造函数的区别与联系 区别 我们构造函数准确的来说不是给成员变量初始化因为初始化只有一次而我们的构造函数的内部可以多次给一个成员变量赋值所以构造函数不是初始化是赋值而初始化列表中的成员变量只会出现一次所以就只会初始化一次。 关系 可以在初始化列表和构造函数体内部同时使用当我们需要一些变量初始化时需要条件判断就要放在构造函数体内部。能用初始化列表都用初始化列表除非必须用构造函数。 4.为什么一定要用初始化列表来初始化引用和const类型 因为我们在没有初始化列表的时候我们写了构造函数但是会发现这样一个现象当没有进入构造函数的时候成员变量都是随机值那这个随机值是在哪里给的呢答案就是初始化列表所以初始化列表是一直存在的只不过在没有显式地写的情况下是默认给随机值的。 了解这些之后我们再来谈谈const修饰的成员变量因为const修饰的变量只能初始化一次不可以被修改所以在我们不写初始化列表时默认的初始化列表就会初始化一次const那接下来我们又在构造函数体内部赋值是肯定错误的那对于引用这样的变量必须是在定义的时候初始化如果我们不使用初始化列表引用类型的成员变量就是默认初始化列表的随机值的别名因为引用是改变不了指向的对象的所以就会出错基于这个原因引用才必须在初始化列表中初始化