作者:几冬雪来
时间:2023年4月25日
内容:C++类和对象讲解
目录
前言:
在上一篇博客中我们补齐了一些C++入门时候的内容,并且在章节的最后引出了我们C++中一个重要的知识点——类和对象。在那里我们也对类和对象里面的一些内容进行了一个大致初步的说明,而今天我们将继续学习我们的类和对象板块的知识。
1.this指针:
在上一篇博客中,我们讲解到了,在结构体中的成员函数,这个函数其实是公共的,它在公共的代码区域,也就是访问函数的地址是相同的。
这里我们可以看出来它们的地址是一样的,但是如果它们访问的地址是一样的话,那么是这么做到的打印的值是不一样的? 它并不是直接不一样的,在这里它有一个隐藏的——this指针,也就是在我们传参数的地方有一个隐藏的this指针。
在这里我们的编译器就会对我们的代码进行暗箱处理,使它们的形参不同。
而在这里因为它们进行的是暗箱处理的,所以我们在这里看到的只是上面的这种代码。那么这里就有人要问了,要是我们想看到它们的暗箱操作,可以写下面这种代码吗? 答案是:不可以。
在编译器中我们规定,this指针不能在形参和实参显示传递,但是可以在函数的内部显示的使用。
既然this是一个指针,那么我们能不能将其进行修改将其变为一个空指针呢?这种行为也是不行的,因为我们的this类型的原因。
因为const的存在,所以我们的this指针不能进行修改。
那么在这里我们的this指针是存放在哪里的?这里的答案是,我们的this指针是存放在栈区的。虽然它是一个指针,但是在我们的代码中它实现的操作为我们形参的操作,因此在这里我们可以将我们的this指针作为形参,而参数存在在栈区中,所以this指针也在栈区中。
在这里就是我们的一个this指针一个经典的题目。
2.默认成员函数:
记得在我们写顺序表或者单向链表的时候,在书写它们的时候在一开始我们就要对其进行初始化的操作,在return的时候又要进行释放的操作。
但是,在书写的过程中,有的时候我们难免会忘记写这两个成员函数,以至于我们的代码出现了问题。
而为了解决这个问题,在C++中我们引入了默认成员函数。那么在这里什么是默认成员函数呢,我们来看看一张表。
在这里在我们日常运用中和需要了解到的默认成员函数为前4个默认成员函数。
3.构造函数:
从上面的图表来看,构造函数在我们的结构体中完成的是我们初始化的工作。那么什么是构造函数呢? 首先这里的构造函数是我们一种特殊的成员函数,我们不能将它和以前的成员函数混为一谈。
构造函数虽然名为构造,但是它的主要作用并不是开空间创造对象,而且初始化对象。那么在这里说我们的构造函数是特殊的成员函数,它特殊在哪里呢?
那么在这里我们的构造函数是怎么样书写的?
并且我们通过一系列的试验也可以在这里论证我们的第三个特征,也就是编译器会帮我们自动调用。
那么对应的构造函数的重载又是什么意思呢?因为在我们的构造函数中,我们具有很多种初始化的方式,所以在这里就需要我们的函数重载来实现这个操作。
在这里就是我们的构造函数的全过程了。
4.析构函数:
讲解完了构造函数,那么接下来我们就要讲解我们的析构函数了,析构函数的定位和我们的构造函数相反,它主要负责的是清理工作。 并且析构函数会在对象销毁的时候自动调用。
同样的我们的析构函数也是特殊的成员函数,也有它的特征:
那么下来既然有了构造函数的代码经验我们也就直接将代码进行书写。
在这里我们和构造结构体一样,一开始要调用我们的类名,并且在类之前加入~符号。 在对象的生命周期结束的时候我们会自动的调用它们。
5.构造函数的问题:
在讲解完了我们的构造函数和析构函数之后,在这里我们提出一个存在于构造函数中的问题。
这里有没有构造函数?答案是:有的。我们的编译器规定,如果类中没有显示定义的构造函数,C++编译器会自动生成一个无参的默认构造函数。
但是在这里我们运行起来就会发现一个点。
在这里虽然生成了无参的默认构造函数,但是它却是一堆随机值。那么在这里我们的C++编译器难道什么都没有做吗?其实并不是的。这里就要牵扯出我们C++中里面的一些规定了。
在这里我们将我们的类型分为内置类型和自定义类型。类似上面那种情况在不写的情况下,编译器会生成构造函数,类似整形这种,它并不会进行处理,所以在输出我们就会看到一堆随机值。但是如果是自定义函数的话,它就会去调用它的默认构造,在这里就会对其进行处理。
只不过这种方式并不是在哪种编译器都会实现,有些编译器不进行处理,有些编译器会对其进行处理,但是这是一种个性化行为。
那么在什么情况下可以让我们的编译器自动生成呢?
根据上面的一系列的操作,我们总结出来了一个结论。
1.一般情况下,有内置类型成员的话,就需要我们自己写构造函数,不能由编译器自动构成。
2.全部是自定义类型成员可以考虑让编译器自己生成。
而在C++11中我们给予了一个补丁,那就是在构造函数的那里我们可以给缺省值。
同样的我们的构造函数的调用根普通函数的调用也不一样。
如果在main函数中,我们的d1如上面这样进行无参调用的时候也会出现一点问题。
根据我们以前学习的知识可以确认,这两个函数可以同时存在,因为一个参数为空,一个有参数所以在这里它们两个函数可以构成函数重载,但是在进行无参调用的时候,我们的调用无法确定要调用哪一个。所以在写函数的时候,两个函数我们只选其中的一种,而一般我们就选择下面的那一种方式,也就是全缺省。
同时我们在有些特定类中也可以由编译器来为我们自动创建析构函数。
结尾:
很快的我们的C++的一个小板块就要学习结束了,相信学习到了这里,大家隐隐约约可以感觉到我们的难度在上升了吧,但是在我们将C++初步掌握好了之后,那之后学习C++就不会觉得那么难了(大概)。最后希望这篇博客能为各位带来帮助。