类与对象初入(c++)

我们从以下几方面先来初步认识c++中的类和对象.

一.面向过程和面向对象

我们学习c++之前得先了解什么是面向过程,什么是面向对象,这样才能帮助我们更好的学习c++,先来看他们的定义:

面向过程:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了.

面向对象:面向对象是把构成问题的事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为.(现实生活中的任何事物都可以看做对象)

知道其定义后我们会发现我们常用的C语言就是面向过程的语言,那么c++就是面向对象的语言,但还有一点要说c++并不是纯面向对象的语言,他是基于面向对象-->既有面向过程,也有面向对象.

二.类和对象的引入

什么是类?

类: 用来对实体(对象)进行描述的,对象有什么属性,对象有什么功能,是一种自定义类型,类定义好了之后,不能直接在类中存储数据.

什么是对象?

对象: 现实生活中实实在在存在的,对象是对类的具体的体现,对象是用类类型创建出来的变量,对象可以存储数据.(对象可以看成是类的实例化)

举个例子方便大家理解: 相信有些朋友已经到了该结婚的年龄了,或者家里已经催婚了,这时有女朋友的自然不用多说,没女朋友的就需要去相亲了,很多城市都会有那种线下相亲的"广场",要相亲的人或者他们的亲戚朋友都会将这个人的信息打印到纸上让别人进行了解,例如:年龄,工作,性别,身高,爱好,学历等等,而这张纸我们就可以将其看成一个类,它是对那个具体的人的信息进行的描述,而这张纸所对应的人就是对象,是一个实实在在存在的实物.

三.类的定义

1.class

class className
{
 // 类体:由成员函数和成员变量组成
 
}; // 一定要注意后面的分号

2.struct

struct className
{
 // 类体:由成员函数和成员变量组成
 
}; // 一定要注意后面的分号

定义类的关键字有两种,一种是struct一种是class,struct定义的类成员的默认访问权限是public(对于访问权限不懂得可以看下后面的访问限定符),而class定义的类默认的访问权限是private,而定义的方式也有两种,方式一: 将类的声明和定义全放在类中定义.方式二: 头文件中放类的声明,原文件中放类的定义(我们一般都会使用方式二进行定义).

我们下面以class来举例进行说明:

方式一:在原文件中将类的声明和定义全放在类体中.

 方式二:在头文件中进行声明,原文件中进行定义.

四.封装和类的访问限定符

既然我们学的是c++,那么面向对象的三大特征(四大特征)一定要知道:封装,继承,多态(如果说的是四大特征就加上抽象 : 抽象就是对一个复杂事物的认知过程),在这篇文章中只针对封装进行介绍.

什么是封装?

 封装是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互.(函数就是一种封装,电脑,手机也是一种封装)

c++是如何体现封装的?

将数据和操作数据的方法进行有机结合可以看成类,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互可以看成访问权限.(控制那些成员可以在类外直接被访问)

什么是访问限定符(访问权限)?

用于对类中的成员变量和成员函数进行限定,使用public进行限定的成员变量和成员函数在类外可以直接被访问,使用protected和private限定的成员变量和成员函数在类外无法直接被访问,另外注意访问权限的作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,具体看下面代码.

1.在头文件中进行类的声明时我给成员变量和成员函数都加上了public的访问权限,这就意味着我们在类外可以直接对其进行访问,另外注意第一个public的作用域从:后到下一个public出现之前,第二个public的作用域从:后到类结束.

 这时我们在main中直接对类中的input和output进行了访问,显然访问成功,代码成功运行没有任何问题.

2.在头文件中进行类的声明时我给成员变量和成员函数都加上了private的访问权限,这就意味着我们在类外不能直接对其进行访问.

 这时我们就会发现再次在main中访问input和output时程序就会报错并产生提示,这便向我们说明了访问限定符的作用.

类的作用域:

在上面图片中我们看到对类中的成员函数在类外进行定义时,都是classname :: 成员函数这种形式这是因为类的作用域的原因,类定义了一个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域.

五.计算类对象的大小

a.非空类的大小

想要求类对象的大小,我们首先要知道类对象中包含什么,经过实际验证我们发现对象中只包含成员变量,因此对象的大小和C语言中求结构体的大小类似,只要注意内存对齐即可.

实际验证:

还是上面的代码:我们多次改变类中成员变量的数目和类型,然后在其中使用sizeof()直接打印类和对象的大小后发现其大小只跟成员变量有关,并且其计算方法与C语言中求结构体大小类似,因此只要在注意内存对齐的情况下求类中"成员变量"之和即可.

那么具体的计算方法是什么呢?我们首先得了解结构体内的内存对齐规则.

1.第一个成员在与结构体偏移量为0的地址处。

2.其他成员变量要对齐到对齐数的整数倍的地址处。

3.对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。(vs默认是8)

4.结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

5.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

那么接下来以这个规则具体的计算一遍.

第一步:先找出第一个成员b的位置,从0字节处开始,占了一个字节,再看第二个成员a的位置,a的对齐数为4(4<8),所以a应该从第四个字节处开始向后占四个字节,再看第三个成员c的位置,c的对齐数为8(8和8相等取那个都行),所以c从第八个字节处开始向后占八个字节,再看第四个成员d的位置,d的对齐数为4(4<8),所以d从第十六个字节处开始向后占4个字节.

第二步:再判断类总的大小为:最大对齐数的倍数24.

b.空类的大小

假设空类大小为0,我们在使用空类来创建对象时,如果连续创建多个对象就会出现问题,因为空类的大小为0,所以创建出来的对象大小也为0,那么它并不会占用这一块空间,因此所有对象都在这块位置创建,他们的地址都一样,此时我们如何区分这些对象呢?答案是没法区分,因此c++为了避免这种情况发生,专门对空类的大小进行了规定,使其不为0,这种情况自然也就不会发生,一般情况下空类的大小设定为1个字节,但是不同的编译器也可能有不同.

六.this指针

1.我们在使用对象调用类成员函数的时候,会不会有这种疑问?在我们类中的成员函数中没有任何关于对象的说明,那么我们使用对象来调用这些方法,他们是如何知道要对那个对象进行操作? 通过接下来的介绍相信能帮助你解决这个疑问.

首先我们想想在C语言中如何使用结构体来调用函数呢?一般情况都是将结构体变量的地址传进函数,然后使用->符号对结构体变量中的数据进行操作.具体如下图:

下面左边这就是C语言中调用结构体变量的过程,因此可以使函数识别结构体变量中的数据.但右边c++中如何使成员函数识别对象中的数据呢?接着向下看..

2.我们直接从c++ 的反汇编指令下观看就会发现问题,c++调用成员函数在3个参数压栈后并没有结束,而是将对象d的地址放到了寄存器ecx中供成员函数进行使用,因此我们可以断定在c++中进行函数调用时和C语言相似都会使用变量的地址来操作数据.

3.相信到这大家应该明白this指针的作用了吧,先来看看它的定义: c++中通过引入this指针解决问题,c++编译器给每个"非静态成员函数"增加了一个隐藏指针参数,让该指针指向当前对象(调用该函数的对象),在函数体中所以"成员变量"的操作,都是通过该指针去访问的,只不过所有操作对于用户都是透明的,即用户不需要自己传递,编译器自动完成.因此对于下面这段函数调用,它的真实形式可以看成:

d1.Init(3,15, 2022 ); (对象调用方法) 这时编译器会将该调用转换成---->Data::Init(&d1,3,15,2022);

这里的&d1的位置就是this指针所在的位置,而在函数体中访问数据也是使用->该符号解析d1的地址进行数据操作,但是在c++中这些操作都被编译器隐藏了,都是透明的,并且不需要用户进行传递和解析,编译器会帮我们完成,所以最终我们使用c++写出来的代码是上面那种,但其底层实现原理与C语言中相同,只不过编译器帮我们完成了隐藏的部分.

注意: 1.this的作用域在类"成员函数"的内部.

          2.this指针可以为空,只要在成员函数中我们没有访问到this指针,就不会对程序造成影响.下面我们将空指针传给this,再调用成员函数,此时我们看到打印出的this指针中的地址为空,但程序并不会崩溃.

因此对于this指针我们可以总结出以下特性:

1. this指针的类型:类类型* const

2. 只能在“成员函数”的内部使用.

3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参.所以对象中不存储this指针.

4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递.

猜你喜欢

转载自blog.csdn.net/weixin_49312527/article/details/123527693