前言:
c++其实顾名思义就是c语言的升级版,很多刚学c++的同学第一感觉就是比c语言难学很多,其实没错,c++里的知识更加难以理解可以说杂且抽象,光是类和对象,看起来容易,但想完全吃透,真的挺难,所以我打算用三篇博客一起归纳介绍一下c++中关于类和对象的所有知识点。
面向过程?面向对象?
c语言是一门面向过程的语言,关注过程。
c++是一门面向对象的语言,关注对象。
那究竟什么是对象?什么是过程呢?
举个例子面向过程,我们洗衣服,一共有下面这些步骤:
c语言就是关注过程,将这些过程一个一个用函数实现就能达到目的。
而c++注重对象比如送外卖,c++就关注商家 买家 骑手等对象,然后每个对象里面又要显示他们的状态,比如骑手就有休息中,派送中,取餐中等,如下图所示:
类的定义:
c++是兼容c语言的,所以在c++中完全可以像c一样使用struct,同时c++将struct升级成了类,我们在类里面可以定义函数,升级成类后又要兼容c,有点矛盾,所以加了一个新的关键字class,所以c++中一般用class来表示类,如下图定义一个日期类:
所以不难看出c语言的struct和class一个重要区别就是class可以在里面定义函数,而且类的定义不必像struct一样加上类型,类名就是类型。
访问方法如下图:
其实光这样是访问不了函数的,接下来就需要我们的域作用限定符了。
域作用限定符:
c++提出了3种访问限定符:
public修饰的成员可以在域外直接被访问。
protected和private在域外不能直接被访问。
至于protected和private的区别,在继承中会体现,这里没什么区别。
如果没有加访问限定符就是默认权限。
那么接下来又有一个struct和class的区别:
class中默认私有。
struct中默认公有。
访问权限作用域从该访问限定符出现到下一个访问限定符出现结束(或者类结束)
如下图设置访问限定符:
在c++的惯例中成员变量都设置为私有,成员函数都设置为公有,因为惯例一般不要直接修改数据,修改数据都要函数去做,当然如果有某些函数你只希望在类里面使用,也可以弄成私有的。
类的声明和定义分离:
当一个类需要声明和定义分离时,不能按以前的方法,简单的声明定义分离,我们先来了解一下编译器的搜索原则:先局部域再全局域
类会形成一个新的域叫类域。
所以编译器默认不会去类域里面查找,所以就可能会出现定义找不到的情况,正确的声明和定义分离如下图:
头文件:
.cpp定义文件:
可以注意到此时需要在定义文件的函数名前面加上 域名::
这样编译器就会优先去该域里面查找。
计算类的大小:
既然类中可以存放函数那么类的大小跟这些函数有关系吗?函数的地址存放在类里面吗?我们可以写一个小案例测试一下。
注意成员变量的存放还是跟结构体一样遵循内存对齐,不懂内存对齐的可以看我的上一篇文章。
通过上面的测试不难看出,计算类的大小时没有算Init函数的大小,说明成员函数的地址没有存放在类里面,那它存放在哪里呢?
类的成员函数地址统一存放在一个公共区域(代码段),避免空间浪费。
写个小案例证明一下上面的结论:
我们把s1变成了空指针,但这里仍能进行正常运行,因为Print的地址在代码段,没在类里面,所以编译器没有对空指针的解引用,而是直接去代码段找到了函数的地址。
冷知识:
如果没有成员变量,只有成员函数又或者都没有的情况,类的大小是多少呢?
这两种的情况,类的大小都规定是1,因为如果一点空间都不给,就无法证明这个类存在过。
this指针:
所有成员函数都i有一个隐含的this指针,它是成员函数的第一个参数。
该指针指向该对象,也就是说改类里的所有成员都可以通过this指针访问。
举个简单的例子:
原本我们的类是这样的:
但当编译器翻译过后就会先变成这样:
注意我们不能显示写this,不然会报错,和上图一样。
this指针被const了无法被修改,可以注意一下const的位置,补充一个小知识点:
const在*前 修饰指针指向的内容
const在*后 修饰指针本身
其实根据它的作用也可以判断出,可以用过this指针修改指向的内容,但不能修改指针本身。
它在函数内部是可以使用的,如下图:
this指针特性总结:
1.在形参和实参的位置我们不能显示写(别跟编译器抢活)
2.它在函数内部可以使用
3.const了,无法修改指针本身
4.因为它是所有成员函数的第一个参数,所有成员函数参数的个数永远都是n+1个
面试中this指针常考问题:
1.this指针存在哪里?
在堆?栈?常量区?静态区?对象里面?
首先对象里面肯定排除,因为我们刚才计算类的大小的时候通过测试,并没有计算this指针的大小,所以排除对象里面。
再排除堆,因为只有malloc的空间才会在堆里面。
还可以排除静态区,因为只有static和全局变量才在静态区。
继续排除常量区,因为在c++中const的变量不在常量区
所以正确答案:栈 因为this指针是一个形参,而栈是用来存放 函数的返回地址、形参、局部变量、返回类型的。
2.下面代码的能正常运行吗?
正确答案是,程序奔溃,这里找到Print函数可以直接去代码段找,但执行该函数时,需要访问里面的_a,所以对s1进行了访问,而s1是空指针,这里出现了对空指针的解引用,所以程序奔溃。
类和对象上篇到此结束,中篇和下篇我会陆续发布,可以点我主页查看,宝藏博主,还不关注,干货满满,火速收藏!!!