C++初阶(长期更新)第2讲:类和对象(上)

C++初阶(长期更新)第2讲:类和对象(上)

C++初阶(长期更新)第2讲:

类和对象(上)

跟着潼心走,轻松拿捏C++,困惑通通走,一去不回头~欢迎开始今天的学习内容,你的支持就是博主最大的动力博主主页:潼心1412o-CSDN博客


前言

好了,下面我们要进入C++真正的核心内容。今天开始学习的类和对象也是C++区别于C语言和其他语言最关键的一部分,gogogo,出发喽~

一、类的定义

1.1 类的定义

定义:class为定义类的关键字,Stack为类的名字,{}中为类的主体

注意类定义结束时后⾯分号不能省略。

类体中内容称为类的成员

类中的变量称为类的属性成员变量

类中的函数称为类的方法或者成员函数

为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_ 或者 m开头,注意C++中这个并不是强制的,只是⼀些惯例,具体看公司的要求。

C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类。

定义在类⾯的成员函数默认为inline。

1.2 访问限定符

类的定义讲了,那到底有什么作用呢?

功能:类是C++实现封装的一种方式,将对象的属性和方法结合在一块,让对象更加完善,通过访问权限选择性将其接口提供给外部用户使用

访问限定符就是用来提供访问权限的,有三种public private 和protected

public修饰的对象可以在类外被直接访问,而protected和private不能直接访问

访问限定符的访问权限作用域从该访问限定符出现开始到下一个访问限定符出现为止,若没有,作用域就到}即类结束

1.3 类域

类定义了一个新的作用域,类所有成员都在类的作用域中,在类外定义成员时,需使用::作用域操作符指明属于哪个类域

类域影响的是编译的查找规则

找不到会编译报错

二、实例化

2.1 实例化概念

实例化定义:用类类型在物理内存中创建对象的过程,称为类实例化出对象

类是什么:对于对象的一种抽象描述,是一种模型一样的东西,限定了类有哪些成员变量,这些对象在类中只是进行了声明,没有分配空间,用类实例化出对象时,这时才会给对象分配空间。

类可以实例化多个对象,就好比一张图纸可以造出许多房子(即实例化出来的对象)

而图纸是不占据空间的,只有房子才会占据空间,用于存储内容

2.2 对象的大小

类对象只存储成员变量,不存储成员函数及指针

why?首先,函数编译后是一段指令,对象中无法存储,这些指令被存储在一个单独的区域(代码段),对象中若是非要存储只能存储函数指针,而对象中是否有存函数指针的必要呢?每个对象中的成员函数的指针都是一样的,而要是用类实例化100个对象,那么同样的函数指针就会重复存储100次,十分浪费。实际上函数指针也是不需要存储的。后续会讲需要存储的场景

类只存储成员变量,怎么存储呢?C++规定类实例化的对象也必须符合内存对齐规则

内存对齐规则

第一个成员在与结构体/类偏移量为0的地址处

其他成员变量要对齐在某一个数字(对齐数)的整数倍地址处

对齐数=编译器默认对齐数与该成员大小的较小值(VS默认值为8)

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

若嵌套结构体,则嵌套结构体对敲到自己最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数(包括嵌套结构体的对齐数)的整数倍

这里的1是占位作用,给1个字节标识对象存在

内存对齐意义:以空间换时间,提高效率

三、this指针

对于类中的成员函数,函数体中没有关于不同对象的区分。那函数调用时怎么知道应该访问哪个对象呢?C++给了⼀个隐含的this指针解决这⾥的问题

编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year,int month, int day)

类的成员函数中访问成员变量,本质是通过this指针访问,如Init函数中给_year赋值, this->_year = year;

C++规定不能在实参和形参的位置显示地写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针

四、综合题

1.下面程序编译运行结果是() A、编译报错 B、运行崩溃 C、正常运行

解析:这道题的核心是空指针的解引用问题。如果空指针解引用就会触发运行报错,注意在此处编译报错是万万不可选的。因为编译报错是语法问题,在此处不涉及到语法错误。

那么这道题是否有空指针解引用呢?结合我们前面学过的内容,我们知道p->Print()这条指令汇编层面实际上是call Print函数的地址。而我们知道函数地址并不存放在对象,在此处即空指针指向的内容。所以在这里空指针并没有解引用也就不存在运行报错。

答案选C

2.下面程序编译运行结果是() A、编译报错 B、运行崩溃 C、正常运行

这里因为我们前面知道在函数内部访问成员变量时都是通过this指针访问的this->_a,而在这里this其实就是p,在这里相当于发生了p这个空指针nullptr的解引用,所以发生运行崩溃

这里答案选B

3.this指针存在内存哪个区域?

A. 栈 B.堆 C.静态区 D.常量区 E.对象⾥⾯
我们知道,在存放内容上,栈stack用于存放局部(临时)变量,局部数组,函数形参;

堆Heap用于存放手动申请的动态内存,即C中的malloc free,C++中的new delete;

静态区用于存放全局变量和static修饰的局部静态变量;

常量区用于存储常量(注意const修饰的具有常性的变量不代表常量不存放在常量区,const只是编译器语法限制不允许赋值改写);

对象可以是栈上对象即局部普通对象,也可以是堆上对象即new动态创建,也可以是全局静态对象(注意类的static成员变量不属于任何对象实例,存放于静态区,所有对象共享一份)

那我们首先可以确认的是this肯定不在对象里面,我们前面讲过对象里面只存放成员变量

this 是什么,成员函数的隐含形参,编译器自动给成员函数追加的第一个参数,不属于具体对象,通过this访问对象栈、堆里面的成员变量,this永远指向调用该函数的对象本体(栈对象、堆对象)

既然是形参,this 指针是存储在栈上的。

下面我们看一下具体怎么存的


好了今天的学习内容就到这里啦,谢谢你的陪伴,我是潼心,下次再见~如果这篇文章对你有帮助的话。请务必给主播一个一键三连,球球了,这对主播很重要~

博主主页:潼心1412o-CSDN博客