新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++类和对象(上):从定义格式到this指针的深度解析

发布时间:2026/10/2 17:29:24来源:尧图网络
C++类和对象(上):从定义格式到this指针的深度解析
一.类的定义1.类定义格式前言类和对象是最开始祖师爷最想加入的东西最初C叫做“带类的C”在不断的加入新语法后衍化成今天的C。• class为定义类的关键字后加一个类的名字如Stack后加一个{}内部放入类的主体注意类定义的{}结束后面的;不能省略。类主体中的内容称为类的成员类中的变量称为类的成员变量或属性类中的函数称为类的成员函数或方法。变化可以在内部放入函数了这样就可以变量和方法集中在一起。class Stack { int* _arr; int _size; int _capacity; };• 为了区分成员变量和外部的普通变量一般习惯上会给成员变量加一个特殊标识这不是C中强制规定的是为了写代码时方便区分和增加可读性而产生的惯例具体看公司要求。class Date { int _year; int _month; int _day; };• C中的struct也可以定义类C在兼容C的同时把struct升级成了类。最明显的变化是struct中可以定义函数了但是一般情况下我们还是推荐使用class去定义类。C和C中的struct的区别如下//test.c typedef struct ListNode { struct ListNode* next; int val; }LTNode; //test.cpp struct ListNodecpp { ListNodecpp* next; //可以在内部使用名字去定义变量了不用加struct int val; }; int main() { //.c使用了typedef去重命名 LTNode* N1; //.cpp不使用typedef去重命名也不用去加上前面的struct ListNodecpp* N2; return 0; }• 直接定义在类里面的成员函数不做声明和定义分离默认为inline正好inline函数也不支持声明和定义分离。学到这我们可以简单的写一个类去运用一下新接收的知识。class Date { void Init(int year,int month, int day) { _year year; _month month; _day day; //假设成员变量不加特殊标识就会出现 //day day; //因为查找变量是现在局部找它只会把形参day赋值给形参day出现自己给自己赋值的情况 //要不然就这样写也行 //Date::day day; } int _year; int _month; int _day; };2.访问限定符• public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接访问(类内还是可以的)目前protected和private是一样的在后面的继承章节才能体现出二者的区别。• 这是C一种实现封装(约束)的方式用类将对象的属性和方法结合在一起让对象整体更加完善再通过访问限定符选择性的将接口提供给外部的用户使用。• 访问权限作用域是从该访问限定符出现的位置开始直到下一个访问限定符出现为止如果后面没有访问限定符了那作用域就到 } 位置即类结束。class Date { public: void Init(int year, int month, int day) { _year year; _month month; _day day; } private: int _year; int _month; int _day; };• C中class和struct的基本区别class中定义成员没有被访问限定符修饰时默认为privatestruct则默认为public要兼容C语言• 一般成员变量都会被限制为private/protected需要给别人使用的成员函数才会放为public。3.类域• 在前文namespace的地方我们也讲解到类定义了一个新的作用域类的所有成员函数都在类的作用域中在类体外定义成员时在类体内要有其声明就是声明和定义分离时需要使用 :: 作用域限定符指明其属于哪个类域。具体如下class Date { public: void Print(); void Init(int year, int month, int day) { _year year; _month month; _day day; } private: int _year; int _month; int _day; }; void Date::Print() { cout _year / _month / _day endl; }• 和命名空间域一样类域影响的是编译的查找规则。二.实例化1.实例化概念• 用类的类型去在物理内存中创建对象的过程称为类实例化出对象。(说的绕演示一下就好了)//这是一个类 class Student { char* name; char* sex; int age; }; int main() { //用这个类的类型去定义出一个对象这就是实例化了 Student lgf; return 0; }• 类是对象的一个抽象描述是一个类似模具一样的东西限定了对象中有那些成员变量这些成员变量只是声明没有开辟空间(在类之中)只有当用类去实例化出对象时才会去分配空间。• 一个类可以实例化出多个对象实例化出的对象占用实际的物理空间存储类成员变量。2.对象大小• 简单来说一个对象的大小就考虑两点即可①只存成员变量并且有内存对齐。②普通函数不存只有动态多态是在对象中存储的。• 在这里可能有同学有疑问为什么我们实例化出来的对象只存储成员变量呢函数不用存储吗这是因为由一个相同的类去定义出多个对象后多个对象内部存储的数据是一定要分开存储在不同空间的但是它们使用的函数都是相同的去最开始的类定义里找即可不用去存储在每个对象中还浪费空间。class Date { public: void Print(); void Init(int year, int month, int day) { _year year; _month month; _day day; } private: int _year; int _month; int _day; }; void Date::Print() { cout _year / _month / _day endl; } int main() { Date d1; d1.Init(2026, 9, 30); d1.Print(); Date d2; d2.Init(2021, 4, 7); d2.Print(); cout sizeof(d1) endl; return 0; }内存对齐规则(在C中学struct就学过了这里简单复习一下即可)• 第一个成员在与结构体偏移量为0的地址处。• 其他成员变量要对齐到某个数字对齐数的整数倍的地址处。• 注意对齐数 编译器默认的一个对齐数 与 该成员大小的较小值。• VS中默认的对齐数为8• 结构体总大小为最大对齐数所有变量类型最大者与默认对齐参数取最小的整数倍。• 如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大 小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。让我们看以下两个类去猜一下它们的大小class A { }; class B { void print() { //。。。 } }; int main() { A a; B b; cout sizeof(a) endl; cout sizeof(b) endl; }上面的程序运行后我们看到没有成员变量的A和B类对象的大小都是1为什么没有成员变量还要给1个字节呢因为如果一个字节都不给怎么表示对象存在过呢所以这里给1字节纯粹是为了占位标识对象存在。三.this指针• Date类中有Print和Init两个成员函数既然我们上文提到对象中不存储成员函数那么当d1调用print和Init函数是怎么知道应该去访问d1对象还是d2对象呢这里就涉及到了C给了一个隐含的this指针去解决该问题。• 编译器在编译后类成员函数默认都会在形参的第一个位置增加一个当前类类型的指针叫做this指针。比如Date的Init的真实原型为void Init(Date* const this, int year, int month, int day)有趣的是this指针被const修饰了且修饰的是this本身而不是*this这则表明this的指向不可被改变但是this* 的内容可以。• 类成员中访问成员变量本质上都是通过this指针访问的如Init函数中给_year赋值编译器处理后为(注意这是概念模型不是真实可编译代码)void Init(Date* const this, int year, int month, int day) { this-_year year; this-_month month; this-_day day; }而在调用时编译器处理后为Date d; d.Init(2024, 9, 30); // 编译器转换成 Init(d, 2024, 9, 30);//在编译过后Init变成了普通函数调用把d.拆成了d作为第一个实参• C规定不能在实参和形参的位置显示的写this指针编译时编译器会自己处理但是在函数体的内部可以显示的使用this指针。class Date { public: void Print() { cout this endl; } void Init(int year, int month, int day) { _year year; _month month; _day day; } private: int _year; int _month; int _day; }; int main() { Date d; d.Print(); return 0; }在这里的print函数就能打印出this的地址了。完。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

HTTP协议核心机制与Qt工程实践:从报文到QNetworkAccessManager调试 2026/10/2 18:26:26

HTTP协议核心机制与Qt工程实践:从报文到QNetworkAccessManager调试

打开浏览器输入网址回车,页面上出现你要的内容;手机App下拉刷新,新数据瞬间铺满屏幕;智能设备上报温度、摄像头回传画面、小程序里完成一次登录授权——这些看起来完全不相关的场景,背后站的都是同一个东西&#xff1a…

阅读更多 →
ESP32-P4 + ESP32-C5双芯架构:打造自带网关的智能触控屏 2026/10/2 18:26:26

ESP32-P4 + ESP32-C5双芯架构:打造自带网关的智能触控屏

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
iOS超级签名源码搭建指南:Java后端+分发页完整实现 2026/10/2 18:26:26

iOS超级签名源码搭建指南:Java后端+分发页完整实现

简介:一套Java与Vue开发的苹果iOS超级签名源码包,附带安卓合并分发页面,面向需要搭建签名分发平台的开发者或站长。功能覆盖登录注册、共有池证书管理、用户自行上传证书、分发页轮播与简介配置、签名后对接阿里云OSS、七牛云或本地存储下载&…

阅读更多 →
Agent Skill 生态治理:从无序囤积到可审计的技能组合 2026/10/2 18:26:26

Agent Skill 生态治理:从无序囤积到可审计的技能组合

最近在帮团队搭建带 Agent Skill 的智能体项目,发现一个特别有意思的现象:凡是刚开始接触 skill 的人,都经历过一段“无脑装机”的蜜月期——看到什么 skill 都想往 agent 里塞,装完一批发现根本管不过来,版本对不上、…

阅读更多 →
AI情报中枢:基于确定性快照的自动化日报系统设计 2026/10/2 18:26:26

AI情报中枢:基于确定性快照的自动化日报系统设计

项目标题是“AI 日报(2026年9月24日)”,乍一看像一份新闻简报,但实际它根本不是传统意义上的媒体产品——它是一套可复用、可自动化、可定制的AI驱动型信息聚合与轻量级内容生成系统,核心目标不是发布新闻,…

阅读更多 →
本科生降AI率实战:9个工具与避坑指南 2026/10/2 18:26:20

本科生降AI率实战:9个工具与避坑指南

先说句实在话:本科生现在提“降AI率”,多数是被检测报告逼出来的。我见过一个学弟,论文写得四平八稳,结果AIGC检测直接标红62%,导师看完让他拿回去“亲手重写”。他来找我的时候,第一句话就是“有没有工具能…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉