首页/新闻资讯/正文详情

从结构体到对象:正式学习C++类的骨架、封装与this指针

发布时间:2026/9/27 9:39:21 来源:云帆数科 栏目:资讯中心
从结构体到对象:正式学习C++类的骨架、封装与this指针
文章目录1. C在C后的延伸2. 类的基本骨架成员、类域和定义位置2. 类定义中放什么2.2 类内定义与类外定义2.3 class 和 struct 的差别3. 访问限定符封装不是仅仅把数据藏起来3.1 public 和 private3.2 protected 先知晓边界即可4. 对象大小成员变量属于对象成员函数不按对象重复保存5. this 指针成员函数如何找到当前对象5.1 从两个对象调用同一个函数5.2 this 的几个性质5.3 空指针调用成员函数为什么有时不马上崩溃7. 小结1. C在C后的延伸C在保留了大量C的表达方式的同时增加了更强的类型组织和抽象工具一些数据与操作数据的函数可以被组织到同一个类中这正是C面向对象的开始。在C中我们可能这样表示一个日期typedefstructDate{intyear;intmonth;intday;}Date;voidDateInit(Date*d,intyear,intmonth,intday){d-yearyear;d-monthmonth;d-dayday;}voidDatePrint(constDate*d){printf(%d/%d/%d\n,d-year,d-month,d-day);}调用时必须把对象地址显式传给每一个函数Date d;DateInit(d,2026,9,24);DatePrint(d);这种写法可以工作但是它把“哪些函数属于Date”交给了命名习惯来维护。函数写错参数、直接修改不应该暴露的数据与忘记检查日期等等操作是否合乎规则都只能依靠调用者自觉安全性较低。而C类则把这层关系写进类型本身classDate{public:voidInit(intyear,intmonth,intday);voidPrint()const;private:int_year0;int_month0;int_day0;};调用时变成Date d;d.Init(2026,9,24);d.Print();2. 类的基本骨架成员、类域和定义位置2. 类定义中放什么classCounter{public:voidAdd(intvalue){_valuevalue;}intGet()const{return_value;}private:int_value0;};这里定义的是一个计数器对象其拥有其的私有成员变量_value然后拥有两个成员函数一个用于获取当前计数一个用于增加指定数量。class Counter { ... };中的内容叫类体。类体里的变量叫成员变量函数叫成员函数。类定义最后的分号不能省略因为整个类定义在语法上也是一条声明。下面我们创建两个对象first和second让其增加不同的计数Counter first;Counter second;first.Add(3);second.Add(10);std::coutfirst当前计数first.Get()std::endl;std::coutsecond当前计数second.Get()std::endl;运行示例可以看到first和second是两个对象各自拥有一份_value。2.2 类内定义与类外定义代码量较少的成员函数可以直接写在类内较长的函数则通常在类外定义让类体更像一份接口说明classCounter{public:voidAdd(intvalue);intGet()const;private:int_value0;};voidCounter::Add(intvalue){_valuevalue;}intCounter::Get()const{return_value;}Counter::Add中的::表示“到Counter这个类域中寻找Add”。如果省略Counter::编译器会把它当成普通的全局函数无法直接访问_value。对于成员函数的函数头后加的const表示的是此函数不会修改对象的相关成员变量是保护数据的一种方式如果函数不需要修改成员变量的话建议加上增加代码可靠性。2.3 class 和 struct 的差别C 中的 struct 也可以包含成员函数和访问限定符structPoint{voidPrint()const;int_x0;int_y0;};但两者的主要默认规则不同class 的默认访问权限是 privatestruct 的默认访问权限是 public。C 中可以继续使用struct表示简单数据也可以使用class表示需要封装行为的类型。关键不在于关键字哪个“更高级”而在于你是否清楚哪些成员应该暴露给外部struct适合纯数据载体类似 C 结构体数据默认公开简单方便class适合需要封装的类型内部数据默认私有控制对外接口。3. 访问限定符封装不是仅仅把数据藏起来3.1 public 和 privateclassCounter{public:voidAdd(intvalue){if(value0){_valuevalue;}}intGet()const{return_value;}private:int_value0;};当外部想要使用成员变量_value时只能通过 Add 和 Get 使用SafeCounter counter;counter.Add(5);counter._value-100;// 编译错误_value 是 private封装的价值是把规则集中在类内部。以后如果计数器需要限制最大值只改Add就可以调用者不需要知道_value的具体表示方式。访问限定符的作用范围从它出现的位置开始一直持续到下一个访问限定符或类定义结束默认是privateclassExample{int_privateValue0;// 默认 privatepublic:voidSet(intvalue){_privateValuevalue;}private:int_anotherValue0;};3.2 protected 先知晓边界即可protected 在类外不能直接访问和 private 在当前阶段的表现相同。它主要会在继承中体现差异。开始学习类和对象时只需要重点明白需要对外提供的操作放到 public表示细节的数据和辅助函数通常放到 private。4. 对象大小成员变量属于对象成员函数不按对象重复保存观察下面的类型classSmall{public:voidPrint()const{}private:int_value0;};classEmpty{public:voidPrint()const{}};第一个Small类中有一个成员变量而Empty中无成员变量让我们看看其各自的对象大小std::coutSmall类大小sizeof(Small)std::endl;std::coutEmpty类大小sizeof(Empty)std::endl;运行示例可以看到Small至少需要容纳一个int(4个字节)。Empty没有成员变量通常仍然占 1 个字节用来区分不同对象的地址。成员函数编译后是指令不需要在每个对象里复制一份因此一般不计入对象大小。这就引出了成员变量与成员函数的不同存放方式成员变量 vs 成员函数成员变量每个对象独立一份其对应内部的成员变量有各自的内存空间。成员函数整个程序里只有一份所有对象共用。成员函数的代码通常保存一份调用时会根据对象不同而操作对应的成员变量。其内部会依靠编译器隐式传入的this指针实现。类的大小实际和C中结构体相似还是会受到内存对齐影响规则类似第一个成员通常从对象起始地址开始后续成员可能为了满足对齐要求产生填充sizeof是编译器根据布局规则计算出的结果不要只用成员大小简单相加。5. this 指针成员函数如何找到当前对象5.1 从两个对象调用同一个函数classDate{public:voidInit(intyear,intmonth,intday){_yearyear;_monthmonth;_dayday;}voidPrint()const{std::cout_year/_month/_daystd::endl;}private:int_year0;int_month0;int_day0;};intmain(){Date d1;Date d2;d1.Init(2026,9,24);d2.Init(2027,1,1);d1.Print();d2.Print();}Init的函数体没有写d1或d2但两次调用结果不同。原因就是是非静态成员函数会有一个编译器隐含传入的参数this。可以把调用过程近似理解为d1.Init(2026, 9, 24) - 类似 Init(d1, 2026, 9, 24) d2.Init(2027, 1, 1); - 类似 Init(d2, 2027, 1, 1)在真实的 C 语法中我们不需要在调用时手写这个参数但成员函数内部确实可以使用thisvoidDate::Init(intyear,intmonth,intday){this-_yearyear;this-_monthmonth;this-_dayday;}在编写时通常可以省略this-因为编译器知道_year是当前对象的成员。显式写出this指针常用于成员变量和参数同名时或者是为了强调当前对象。5.2this的几个性质this 是成员函数内部可用的指针它指向调用当前成员函数的对象不能修改 this 让它指向另一个对象静态成员函数没有 this因为它不依附于某个具体对象。5.3 空指针调用成员函数为什么有时不马上崩溃观察并运行以下代码classDemo{public:voidHello()const{std::couthellostd::endl;}voidPrintValue()const{std::cout_valuestd::endl;}private:int_value10;};intmain(){Demo*ptrnullptr;ptr-Hello();// 可能看起来能运行ptr-PrintValue();// 访问成员数据通常会崩溃}运行示例从语言规则上说通过空指针调用非静态成员函数本身就是未定义行为不能因为某次运行没有崩溃就认为它是安全的。PrintValue需要通过this找到_value所以更容易触发崩溃。注意不要把这种使用方式当作技巧而是通过这个例子帮助我们理解this指针的存在与作用。7. 小结类不是把 C 语法换一种写法而是把数据、操作和访问边界组织到一个类型中。对象拥有自己的状态成员函数通过隐含的 this 找到当前对象访问限定符则决定外部能否直接触碰这些状态。理解这三层关系后构造函数、析构函数和运算符重载就不再是孤立语法而是继续完善“对象类型”的工具。

相关推荐

皮带机巡检的四个必查点:跑偏、打滑、撕裂、托辊异响怎么判
皮带机巡检的四个必查点:跑偏、打滑、撕裂、托辊异响怎么判

一、跑偏:判定要看三处,不是看一眼 皮带机跑偏是最常见的故障,也是最容易被“凭感觉”处理的一项。真正可验收的判定要落在三个位置:头部滚筒、尾部滚筒、中部托辊组。行业通行口径是胶带中心线相对机架中心线的偏移量不超过带宽… · 2026/9/27 9:39:21

手机版 Lightroom:口袋里的专业影像工作室
手机版 Lightroom:口袋里的专业影像工作室

手机版 Lightroom 是由 Adobe 出品的移动端专业照片编辑应用,承袭了神奇的 Adobe Photoshop 核心技术,让用户可以在智能手机或平板电脑上轻松制作和分享专业级质量的图像。凭借强大的 Raw HDR 功能,它为您带来一流的照片拍摄与处理体验、出色… · 2026/9/27 9:39:15

undici MockClient 完全指南:用单连接 MockClient 拦截 HTTP 请求
undici MockClient 完全指南:用单连接 MockClient 拦截 HTTP 请求

后端网络通信 【免费下载链接】undici An HTTP/1.1 client, written from scratch for Node.js 项目地址: https://gitcode.com/gh_mirrors/un/undici 点击查看 免费下载 MockClient 是 undici 中基于真实 Client 实现的 Mock 调度器:它以单连接模式挂载… · 2026/9/27 9:39:09

避开高价坑从零搭建phpcms网站备份方案
避开高价坑从零搭建phpcms网站备份方案

避开高价坑从零搭建phpcms网站备份方案 找建站公司怕被坑高价,这是很多老板心里的刺。别被那些“全托管”“终身维护”的漂亮话术忽悠了,真正决定网站生死的是底层数据的完整性。… · 2026/9/27 10:21:57

The JavaScript Way:用 JavaScript 修改网页结构、内容与样式的完整实战指南
The JavaScript Way:用 JavaScript 修改网页结构、内容与样式的完整实战指南

教程文档 【免费下载链接】thejsway The JavaScript Way book 项目地址: https://gitcode.com/gh_mirrors/th/thejsway 点击查看 免费下载 本篇对应《The JavaScript Way》第 15 章(Create interactive web pages 系列第 4 篇)。浏览器加载完… · 2026/9/27 10:21:57

基于STM32的实验室消防预警系统:多传感器融合与代码仿真全解析
基于STM32的实验室消防预警系统:多传感器融合与代码仿真全解析

1. 为什么我要用STM32做一套实验室消防预警系统实验室这个场景,跟普通办公室或者住宅有个本质区别:危险源密度极高。一个化学实验室里可能同时存在酒精灯、电热板、易燃试剂、高压气瓶,而人员往往在做实验时高度专注,对周围环境变… · 2026/9/27 10:21:51

对象存储oss怎么用?
对象存储oss怎么用?

阿里云对象存储(OSS, Object Storage Service)(https://www.aliyun.com/product/oss)是阿里云提供的海量、安全、低成本、高持久的云存储服务。它适合存放图片、视频、日志、备份数据等非结构化数据。 以下是 OSS 的核心概念、使… · 2026/9/27 10:21:51

基于STM32的实验室消防预警控制器设计与实现:从硬件选型到Proteus仿真验证
基于STM32的实验室消防预警控制器设计与实现:从硬件选型到Proteus仿真验证

1. 项目缘起与整体设计思路1.1 为什么选择STM32做消防预警控制器实验室场景的消防预警和商用楼宇那种动辄几百个探测点的大系统完全是两码事。一个标准的高校实验室或者企业研发实验室,面积通常在40到120平米之间,需要监控的点位无非是温度、烟雾浓度、可… · 2026/9/27 10:21:45

新闻采集源码wordpress速查手册:报价拆解与域名避坑指南
新闻采集源码wordpress速查手册:报价拆解与域名避坑指南

新闻采集源码wordpress速查手册:报价拆解与域名避坑指南 域名解析报错,服务器SSL证书过期,后台登录直接白屏。这三个场景,是不是让你抓狂?很多老板以为买套“新闻采集源码wordpress”就能自动赚钱,结果卡在部署环节,对着控制台发… · 2026/9/27 10:21:38

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码