当前位置: 首页 > news >正文

C++类和对象(上):一文搞懂基础定义与核心规则

gitee地址:Yu 子淳 (yyyzzzzccc) - Gitee.com

目录

1、类和对象的定义(class)

1.1什么是类?

1.2 类定义格式

1.3代码示例

1.4类的核心组成元素

2、类(class)与结构体(struct)的关系

​编辑3、为啥优先使用class?

4、什么时候反而用 struct?

5、 访问限定符

6、类域作用域与成员访问规则

7、实例化

8、内存对齐原则

9、this指针的讲解


1、类和对象的定义(class)

1.1什么是类?

我们可以把类理解为一张【图纸】,把对象理解为根据图纸造出来的【实物】。

举个生活最直观的例子:

- 汽车图纸:规定了汽车必须有车轮、颜色、品牌(属性),可以行驶、刹车、鸣笛(行为)——这就是类

- 特斯拉、比亚迪、丰田的每一台具体汽车:按照图纸造出来、有具体参数、可以实际使用的实物——这就是对象

简单总结核心关系:类是对象的模板,对象是类的实例。
类只定义「规则和特征」,不占用实际内存;对象是类的具体化,会开辟内存空间,承载真实数据。

1.2 类定义格式

1、class为定义类的关键字,Stack为类的名字,这里的类的名字不是唯一的,可以自定义。{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或者成员函数。

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

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

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

1.3代码示例

这段代码当中,student就是一个类,它只规定了学生[有什么、能做什么],没有具体的年龄和姓名,也没有执行任何操作,只是一个套用模板。

1.4类的核心组成元素

类由属性(成员变量)和方法(成员函数)组成:

属性(成员变量):代表事物的静态特征、数据信息。比如:人的身高,年龄等,属性是用来存储数据,表述[这个事物是什么样子]。

方法(成员函数):代表事物的动态特征,功能操作。比如:人吃饭睡觉,手机拍照联网。方法用来实现逻辑,表述[这个事物能做什么]。

2、类(class)与结构体(struct)的关系

学完类的概念与作用后,绝大多数 C++ 初学者都会遇到同一个困惑:
结构体 struct 看起来和 class 几乎一模一样,也能存数据、写函数,那它和类到底是什么关系?有什么区别?

本章彻底讲透:struct 和 class 的历史关系、底层联系、语法区别、设计定位,一次性终结混淆。

2.1 二者真实关系:struct 是 class 的「前身」

1)C语言时代的 struct(纯数据容器)

C 语言没有类、没有面向对象。
为了把零散变量打包成一个整体,C 设计了 struct ,只能存变量,不能写函数。

它的唯一作用:聚合一组相关数据。

2)C++ 对 struct 进行全面升级

C++ 为了兼容 C 语言,保留了 struct,并给 struct 新增了全套面向对象能力:

- 可以写成员函数

- 可以有构造、析构函数

- 可以继承

- 可以多态

- 可以封装

所以在 C++ 语法层面:struct 和 class 本质是同一个东西。

3)一句话总结二者关系

struct 是 C++ 中弱化版、兼容版的 class。
class 是 C++ 专门为面向对象设计的、规范化的 struct。

它们同源、同结构、同能力,只是默认规则、设计语义、使用场景不同。

3.2 struct 与 class 的完全相同点(重点!很多人不知道)

在 C++ 中,两者语法能力完全一致:

1. 都可以封装成员变量

2. 都可以定义成员函数

3. 都拥有构造函数、析构函数

4. 都支持继承、派生

5. 都支持多态、虚函数

6. 都可以实例化对象

也就是说:你能用 class 写出来的代码,100% 可以用 struct 替代编译通过。

3.3 struct 与 class 的唯一本质语法区别

1)成员默认访问权限不同(核心差异)

- class 默认 private(私有)

- struct 默认 public(公有)

3、为啥优先使用class?

最核心的区别是:默认权限不同

class的默认成员权限是private(私有)。外部无法直接访问访问成员,数据默认被保护。

struct的默认成员是public(公有),所有成员对外完全暴露,任何人都可以直接读写数据。

4、什么时候反而用 struct?

这里补充边界场景,做到完整认知,避免绝对化:
- 简单数据结构体:坐标、点、颜色、报文协议、传输数据等,只有成员变量,没有业务方法,优先用 struct 。

- 兼容 C 语言代码:老项目、底层驱动、嵌入式代码需要兼容 C 语法时,沿用 struct 。

5、 访问限定符

• C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤⼾使⽤。

• public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。

• 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。

• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

• ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。

6、类域作用域与成员访问规则

在前面的讲解当中,我们知道类是一个封装了数据和函数的独立模块。但是在实际开发当中,我们经常遇到一个问题:不创建对象,能不能直接访问类里面的成员?这里就需要用类域::,并结合成员类型和访问权限来判断。在前面的C++基础当中,我们直到::作用域运算符,语法格式为类名::成员名。

它的作用,就是明确告诉编译器:我要访问它的这个成员,属于那个类的。

为啥要创建对象才能访问成员变量呢?是因为我们在前面的讲解中,我们可以把class student比作【学生档案模板】,这些模板上面只写了姓名,年龄,学号这些字段,并没有具体的值。当你创建student s时,就相当于打印了一份空白档案,为s这个学生分配独立的空间,你才可以往里面填写s.age=18;如果不创建对象,就像手中只有一张模板,你没法在模板上直接写年龄=18---因为模板是通用的,不属于任何一个学生。最简陋的说就是你定义的类只是一个模板,没有创建空间,所以你直接把18这个值赋给age,它是没有办法存放的,所以需要先创建变量,才能存放这个值。

7、实例化

什么是实例化呢?

1、实例化就是用类类型在物理内存中创建对象的过程,称为实例化出的对象。

2、我们在上面说了,类是一个模板,需要创建对象才能进行使用,一个类可以创建出多个对象。

如上面我们在开头也讲了,可以把类看作一个设计图纸,对象就是根据设计图纸创建出来的一个个房子,它们的布局都是一样的。

我们写一个以学生为类的模板,我们实例化两个对象d1和d2,我们想一下,我们假如调用50次成员函数,就重复50次吗?太浪费空间是时间了,我们一般把成员函数放一个公共区域,这样每次调用直接在公共区域里面去找,这样就会很方便,我们在这里先不仔细讲解,以后再讲。

8、内存对齐原则

这个我们在之前的文章当中讲解过,这里就不仔细讲解了,我们再次把定义重复一遍,练几道题就过。

• 第⼀个成员在与结构体偏移量为0的地址处。

• 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

• 注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。

• VS中默认的对⻬数为8

• 结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍。

• 如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

注意:在类当中,我们算内存大小只需要计算成员变量,不用算成员函数。如果类当中只有成员函数,只有成员变量,默认内存大小为1,不能为0,代表这个类存在过,这时C++规定。

内存大小的计算:首先第一个成员放到结构体偏移量为0的地址处,它的字节大小是4,所以依次放4个字节,第二个成员要对齐到对齐数的整数倍的地址处,而对齐数=编译器默认值和该成员大小的较小值,而又因为编译器的默认值是8,而这个成员变量的字节大小是1,所以对齐数综合下来就是1,结构体的总大小:最大对齐数(所有成员变量的最大值与默认值的最小)的整数倍,也就是4的整数倍,而现在是5,所以再填3个字节大小凑到8,成为4的倍数。所以总大小是8.

而对于这种只有成员函数,没有成员变量的类,它的内存大小默认是1;

9、this指针的讲解

• student类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了⼀个隐含的this指针解决这⾥的问题

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

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

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

我们可以看到把this指针补上去,也可以正常过,但是在实参和形参的位置没有显示this指针,是因为C++规定,会处理掉this指针,所以这两处没有显示this指针,但是在访问成员变量和打印时我们可以把this指针填上去,也是可以的。

http://www.jsqmd.com/news/934046/

相关文章:

  • Debugger Canvas:可视化调试如何革新代码调试的认知模式
  • 前期安装虽需功夫,但后续操作简单,还支持多实用功能!
  • 36小时打造AR内容推荐引擎:从PWA到向量检索的实战解析
  • 聚力绿色包装创新,interpack China×WPO 上海盛会 11 月启幕
  • 从系统脆弱性到韧性架构:如何防范分布式系统中的“缺口末日”
  • UE5新手避坑指南:手把手教你开启Lumen全局光照,告别漫长的光照烘焙
  • 5分钟快速上手Blue Topaz:打造你的专属Obsidian蓝色主题
  • Win10开机报No Bootable Device别慌!从拍打到重装,我试了这5种方法(附详细命令)
  • 电网设备拓扑图一键自动排布工具(基于FR力导向算法)
  • 职场人必备!高颜值电脑音乐播放器YesPlayMusicV0.4.10
  • LangChain4j AiServices 机制详解:快速构建智能体应用
  • 从Grudin定律到协同设计:人机交互与CSCW的核心思想与实践
  • WSL2下Docker容器GPU挂载报错?手把手教你修复‘libnvidia-ml.so.1: file exists’问题
  • HoloLens 2学术研究指南:混合现实技术原理、开发流程与创新应用
  • 用STM32F103C8T6和AD9850自制高精度信号发生器,从电路焊接、代码编写到波形测试全流程避坑
  • 从Haskell到工程实践:函数式编程思想如何提升代码质量
  • 从Imagine Cup 2011冠军项目看传感器与机器学习的工程实践
  • 第130期《Installer》推荐:多款新品、屏幕分享、读者好物及Spotify实用功能!
  • Sora 2汽车设计展示全解密(行业首份内部演示录屏逐帧分析)
  • 第三周结果
  • GSEA分析避坑指南:从NES、FDR到leading edge,这些参数设置错了结果全白费
  • C#后台导入Excel别再写复杂解析了!MiniExcel一行代码映射到实体类(含表头不对齐的解决方案)
  • 算法优化如何助力生态保护:贪婪与遗传算法的跨界实践
  • Oura Ring 5 发布:体积缩小40%,新增血压追踪与睡眠呼吸分析
  • 2026年天津建设工程律师避坑指南:5位建工经验丰富靠谱推荐 - 本地品牌推荐
  • UE5 GAS实战:手把手教你为RPG角色创建第一个AttributeSet(含Health/Mana完整代码)
  • 别等竞品发布!Sora 2隐藏的“法规预检模式”可自动识别ECE R127灯光合规缺陷(附逆向工程验证报告)
  • 在YOLOv3上实战ASFF:手把手教你用PyTorch实现自适应特征融合,提升小目标检测效果
  • 定理证明器在干细胞生物学中的应用:形式化建模与逻辑推理
  • 从零到一:用Python和SQLAlchemy玩转MIMIC-IV数据库(实战数据分析流程)