C++类和面向对象

相信大家在学习C++的时候听的最多的一句话就是面向对象。包括我们的课本名字都是面向对象的C++编程。但是大家真的明白什么是面向对象的编程吗?到底什么才是面向对象的编程。同样这是一个十分抽象的概念,所以很多人自始至终也解释不清楚到底怎么样才是面向对象。说到面向对象具体是个什么还是需要让他和面向过程对比着说。

  比如我们之前所说的面向过程,简单的来说他的编程就是看着你是如何操作的,他的操作和他所代表的具体数据是分割开来的,更加注重了程序的行为,也就是程序中的函数,不断的通过函数调用,不断的通过一些行为来实现你想实现的功能,但是C++面向对象的时候,就不再是简简单单的执行操作,而是将你的数据和你的对象结合了起来,形成了一个类。C++他和我们现实世界更加的接近,我们并不是简单的操作,我们有我们的特性,有我们的行为,通过每个个体的碰撞操作来实现程序的运行。这个抽象概念在我看来是很不容易理解的。并且大家在说到面向对象的时候常常会说到三大特点:封装、继承、多态。当你的程序中不再是单纯的行为操作,而是和现实世界中一样是一个一个对象,一个一个实体的碰撞等等行为来发生的。这样的话每个个体也就是我们人本身就具有了三个特点,封装,我们每个人都有每个人的隐私,每个人都有每个人的小秘密。都有只有我们自己才能知道的东西。我们在和别人交流的时候别人是不能发现我这些东西的这就是封装。同样我们和现实生活中一样,我们会有继承,我们的有些东西会被我们子类继承到,王思聪这个子类就继承了他爹这个类中的钱,这就是面向对象中的继承概念。多态就更好理解了,我们每个人都是不一样的,无论是长相、发型、性格等等,每个人都有每个人独特的特点,这就是面向对象的多态。这里关键要理解的还是什么才算是面向对象,面向对象总的来说并不像以前那样简单的去执行你的指令,不断的进行操作,这里我们每个操作的对象都是人都是一个类,只有类和类发生碰撞的时候才能有他对应的操作。

  C++中还有一个特殊的东西是C语言中没有的,那就是类,类其实可以看做包括函数的结构体。对类的具体描述我今天就不过多的讲解了,今天主要给大家介绍的是类的一些特性。

第一点:类的大小,类的大小是怎么来计算的?如果类中什么都没有那类的大小是多少?

首先看第一个程序

 

如果之前没有接触过的话会感觉,类里边是有函数的,那么sizeof是怎么来算类的大小的?我所设定的student类中有两个函数,一个是构造函数,一个是输出函数,类中只有一个成员就是_age它是int类型的,那sizeof之后的类是多大呢?

大家不妨先猜想一下,我最初看到的我认为是12ageint类型占了4个空间,剩下了两个函数分别留下了一个指针,我最初是这么认为的,但是因为对C++有过一些了解,这个想法很快就被否定了,因为这两个函数里边是有一个构造函数的,大家都知道构造函数如果设计者没有明确给出的话,编译器是会自己给他补上一个构造函数的,和构造函数类似的还有析构,拷贝构造等等,也就是说可以看成如果你这个类里边只有私有成员没有函数的时候他也是有好几个可以调用的函数,那这时候大小再怎么算呢?所以这么想是不正确的。

大家看一下程序运行之后的结果

 

因为没有带鼠标所以为了方便截图就直接保存屏幕了,大家看最后一行可以看到,sizeof的值是4也就是说,sizeof在计算的时候只计算了他的成员变量,并没有去计算他的成员函数。

这是C++一种很好的机制,类中的特点就是不仅包含了成员变量还有成员函数,所以C++的设计者是将这个类的成员函数单独提出来放到了一个公共的区域,这样无论你定义多少个成员变量总是去调用同一个函数,并不需要每定义一个成员变量的时候都需要将你的函数重新再次定义一遍。所以类的大小是只计算成员变量的大小而不需要去计算成员函数的大小。

那么空类是怎么计算的呢?

 

这次我们将类中的所有函数和变量都删除再去计算类的大小

大家这次可以再猜想一下,我最初的猜想是0.

但是事实上却并不是这样

 

当一个类是空的时候他的大小是1,不知道大家有没有听过类的实例化概念,这里就是实例化的结果,我们编写代码的时候常常只看层面不知道他的底层是怎么实现的,这就导致了很多情况下,程序的结果和我们预料的结果并不是一样的。所谓类的实例化就是,当你定义出来这个类之后,他并不是只有你看到了,编译器对他进行了处理,给他分配了一块只属于他的空间来标明他的存在,当你定义为空的类的时候,编译器为了达到实例化的目的就给他分配了一块隐藏的空间以表明他的存在。这空间不用多大就是1.这也就是为什么空类你求出来的大小不是0了。

 并且这里再多说一些,类和结构体是很类似的,之前我们都知道结构体的内存对齐把我们弄得晕头转向这里类也是的,类也是存在内存对齐的,这里我们就回顾一下内存对齐的规则。

1. 第一个数据永远是放在开始的位置,之后每个数据的对齐数是不定的,他们的对齐数取决于他们自身的大小和当前编译环境对齐数中较小的那个。例如我们现在要放的是int类型,当前编译环境中设定的内存对齐数为8,那这个int类型的对齐数就是4.

2. 当这个结构体每个成员都对齐结束之后,这个结构体整体还要进行对齐,这个结构体的对齐数要是所有成员中对齐数最大的那个数据的对齐数的整数倍,例如我现在这个结构体中的数据最大对齐数是16,那通俗来说这个结构体大小必须是16的整数倍。

 那为什么要内存对齐呢?内存对齐有什么优点呢?

 很多人会说,内存对齐是用空间换取时间的方法提高了访问速度,那他到底是怎么来提高访问速度的呢?今天我给大家简单的提一下。这里简单来说,如果没有内存对齐cpu读取一个数据是可能需要访问两次,要比没有对齐多一次。

例如我们现在定义一个结构体结构体中有三个变量分别是char aint b char c 三个数据分别大小是1,4,1,假如现在编译器的对齐数为4,也就是说现在编译器一次读取4个字节。

 

我想这个图就能很容易理解,这里的b被分成了两份,如果想要读取b的话会需要先读取左边那四个字节,然后再去读取右边那四个自己,有的人可能有疑问,那为什么不能从b的第一个字节开始呢?首先编译器最初并不知道是这样的只有读取结束后才知道,其次,如果从b字节第一个开始读那必定前边读取不是4的倍数,这种情况是不可能存在的。

猜你喜欢

转载自blog.csdn.net/Hanani_Jia/article/details/80857770