C++——类和对象(1)
1. 类
我们之前提及过C语言是面向过程的语言,其解决问题的方式是关注问题过程,然后逐步解决。而C++是面向对象编程,聚焦于对象,依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。
1.1 C++中的结构体
C++兼容C,所以C++的结构体完全涵盖了C语言中结构体的语法形式。除此之外,C++结构体也做出了一些改进,如定义结构体变量不再一定需要struct关键字,不过最大的变化还是体现在结构体内可以定义函数了。
在结构体内定义的函数可以直接使用结构体中的成员变量,在调用成员函数时可以直接使用成员访问的方式就行调用,函数中的成员变量则会自动被替换为调用结构体变量对应的结构体变量。
struct Stack {//C++的结构体内既可以定义变量,也可以定义函数//变量int* _arr;int _capacity;int _top;//函数void Init(int capacity = 4){_arr = (int*)malloc(sizeof(int) * capacity);if (_arr == nullptr){perror("malloc fail");return;}_capacity = capacity;_top = 0;}
};
int main()
{//定义结构体变量可以不加structstruct Stack st1;Stack st2;//调用成员函数st1.Init();st2.Init(8);
}
需要注意的是成员变量的命名,尽量加入一些标识使得可以很容易分辨出是一个成员变量,以防在成员函数中调用产生分不清的情况。类的成员变量命名也要注意这一点。
1.2 C++的类
但是在C++中我们一般使用类来替代结构体,类的关键字为class。
1.2.1 类的定义
1.2.1.1 声明和定义全部放在类体中
声明和定义同时放在类体中,这种方式比较简便,就像C语言阶段的声明定义不分离一样。
class Date
{int _year;int _month;int _day;void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};
1.2.1.2 声明放在类的头文件,定义放在类的实现文件
这种方法类似于C语言中的声明和变量分离,比较规整并且便于合作开发。
这种方法需要注意类的作用域,即需要 类名::成员名 来指明成员所属的类域。
date.h
#pragma once class Date {int _year;int _month;int _day;void Show(); };
date.cpp
#include"date.h" void Date::Show() {cout << _year << '-' << _month << '-' << _day << endl; }
1.2.2 类的访问限定符
1.2.2.1 封装
面向对象有三大特性:封装、继承、多态。
封装指的是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。在C++中可以借助访问限定符,来控制哪些成员或方法可以在类外部使用,从而实现封装的特性。
1.2.2.2 访问限定符
C++的访问限定符有三个:public(公有),protected(保护),private(私有)。这三个访问限定符只有public修饰的成员支持在类外被访问,而protected和private是不可以的。
访问限定符在C++中的形式是访问限定符带一个冒号。其限定范围是自符号起到下一个访问限定符或类结束为止。
class成员的默认访问权限是private,struct成员的默认访问权限是public。
struct Stack {int* _arr;int _capacity;int _top;void Init(int capacity = 4){_arr = (int*)malloc(sizeof(int) * capacity);if (_arr == nullptr){perror("malloc fail");return;}_capacity = capacity;_top = 0;}
private:void Show(){}
};
class Date
{int _year;int _month;int _day;public:void Init(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};int main()
{struct Stack st1;//struct默认访问权限是publicst1.Init();int a = st1._capacity;//st1.Show();//errorDate d1;//class默认访问权限是private//d1._year = 2024; //errord1.Init();d1.Show();
}
1.2.3 类的实例化
类和结构体在一定程度上是相似的。在定义结构体或类的时候只是限定了有哪些成员,类似于给出图纸,但此时并没有在内存中分配空间。直到我们创建结构体变量或类对象,这时候才会在内存中开辟空间,我们才能正常访问使用。这一步就叫做类的实例化。
class Date
{int _year;int _month;int _day;public:void Init(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};int main()
{//Date.Init(); //error 没有实例化Date d1;d1.Init();
}
1.2.4 类的大小
类的大小计算方式与结构体相同。类中的成员函数不会存放在对象开辟的空间中,而是统一放在代码段中。所以类的大小只与成员变量有关而与成员函数无关。当类中没有成员函数时,编译器中会为这个空类对象分配一个字节的空间作为占位。
class C1
{int a;char c;double d;void func(){}
};
class C2
{void func(){}
};
class C3
{};int main()
{cout << sizeof(C1) << endl; //16cout << sizeof(C2) << endl; //1cout << sizeof(C3) << endl; //1
}
1.3 this指针
在了解了这么多后有一个问题,在调用成员函数时,我们并没有传递对象的相关信息,函数凭什么知道我们调用的对象是d1而不是d2呢?这是因为this指针发挥了作用。
在C++中,编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数这也就是我们所要介绍的this指针。函数调用时,this指针会指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过this指针去访问的。只不过所有的操作对用户是透明的,即用户不需要来传递,由编译器自动完成。
我们可以通过观察汇编代码发现这个隐藏的this指针传参。
class Date
{int _year;int _month;int _day;public://void Init(Date* const this, int year = 2000, int month = 1, int day = 1)void Init(int year = 2000, int month = 1, int day = 1) {this->_year = year;_month = month;_day = day;}//void Show(Date* const this)void Show(){cout << _year << '-' << _month << '-' << _day << endl;}
};
int main()
{Date d1;d1.Init(2024, 2, 25);d1.Show();
}
我们对this指针进行总结:
①this指针的类型是 类类型* const,这说明在函数成员内不可以修改this,但是修改通过this解引用的值。
②this指针只能在成员函数内使用。
③对象中并不储存this指针,在成员函数调用时将对象的地址作为实参传递给成员函数的this形参。
④this指针真实存在,但是传参是由编译器自动完成的,我们不可以在实参和形参位置显式写出this指针的传递。
⑤我们可以在成员函数内部使用this指针。this作为参数,存储在栈中。
class C
{
public:int _a;void func(){cout << "func()" << endl; //没有使用this指针,所以没有空指针解引用,不报错//cout << _a << endl; //error 实际上是this->_a,this是空指针,所以报错}
};
int main()
{C c1;C* pc = nullptr;pc->func(); //-> 不解引用,而是将pc作为参数传给this,this接收参数,值为nullptr(*pc).func(); //. 不解引用,也是将pc传给this指针,this接收参数,值为nullptr
}
在成员函数调用时,->或.两个操作符并不进行解引用,而是表示将传给this指针的对象是谁,所以在主函数中并未报错,在成员函数中访问成员变量时才会对this解引用。
相关文章:

C++——类和对象(1)
1. 类 我们之前提及过C语言是面向过程的语言,其解决问题的方式是关注问题过程,然后逐步解决。而C是面向对象编程,聚焦于对象,依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。 1.1 C中的结构体…...

vue+element ui上传图片到七牛云服务器
本来打算做一个全部都是前端完成的资源上传到七牛云的demo,但是需要获取token,经历了九九八十一难,最终还是选择放弃,token从后端获取(springboot)。如果你们有前端直接能解决的麻烦记得私我哦!…...

学不动系列-git-hooks和husky+lintstage
git-hooks 为了保证提交的代码符合规范,可以在上传代码时进行校验。常用husky来协助进行代码提交时的eslint校验。husky是基于git-hooks来实现,在使用husky之前,我们先来研究一下git-hooks。 构建git-hooks测试项目 需要使用git-hooks就需…...
K8S相关小技巧《四》
需求: 我作为Kubernetes的集群管理员,前一段时间有收到一个需求,需要我创建一个受限访问的用户kubeconfig,提供给跳板机的某用户。 该kubeconfig需要在非Kubernetes节点的某跳板机上由指定的非root用户使用,该用户仅能…...

Delphi 报错 Type androidx.collection.ArraySet is defined multiple times
Delphi 11 建立一个新的 Multi-Device Application 编译成app的时候报错 报错信息 [PAClient Error] Error: E7688 Unable to execute "E:\Program\Java\jdk1.8.0_301\bin\java.exe" -cp "e:\program\embarcadero\studio\22.0\bin\Android\r8-3.3.28.jar"…...
Post请求中文乱码问题
url*************************************这里填写自己请求的网址 response requests.post(url, datajson.dumps(body),headersheader) r response.text print 打印乱码长这样: data:{“code”:0,“data”:{“end”:false,“message”:“{\n “ˆ—¡A”: [“…...

LeetCode -- 79.单词搜索
1. 问题描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水…...

单元测试、集成测试、系统测试有什么不同?
单元测试、集成测试和系统测试是软件测试开发中不可或缺的部分。 单元测试: 范围:单元测试是对软件中最小的可测试单元的测试,通常是函数、方法或类。 目的:它的目标是验证每个单独的单元是否按照预期工作,以增加代码…...

数据迁移DTS | 云上MySQL 数据库迁移至达梦数据库
引入 云上 MySQL 数据库 —> 向达梦国产化数据库迁移 下载&安装 达梦客户端工具 DM->可参考之前国产化专栏达梦文章 创建模式 在客户端分别依次执行以下命令脚本(这里没有通过客户端管理工具去创建达梦数据库的模式,当然也可以通过图形化界…...

Linux进程管理:(二)进程调度原语
文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 进程调度的概念比较简单,…...
Compose 介绍
Compose 介绍 Android Compose 是 Google 官方推出的用于构建原生 Android UI 的现代工具包。它使用 Kotlin 语言编写,可以帮助开发人员更轻松、更快速地创建精美、响应式和高性能的 Android 应用。 Compose 的优势 声明式 UI: Compose 使用声明式 UI…...

5分钟搞定Python中函数的参数
函数的灵活性非常高,除了常规定义的位置参数以外,还支持默认参数、关键字参数、以及可变参数 ... 这样以来,不但能应对各种复杂的情况,甚至还可以简化调用者的代码。 位置参数 在调用函数时,一般会根据函数定义的参数…...

Gitlab: 私有化部署
目录 1. 说明 2. 资源要求 3. 安装 4. 配置实践 4.1 服务器 4.2 人员与项目 4.2 部署准备 4.2.1 访问变量及用户账号设置 4.2.2 Runner设置 4.2.3 要点 5. 应用项目 CI/CD 6. 参考 1. 说明 gitlab是一个强大且免费的代码管理/部署工具,能统一集成代码仓…...

深入理解Linux线程(LWP):概念、结构与实现机制(2)
🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:会いたい—Naomile 1:12━━━━━━️💟──────── 4:59 🔄 ◀️ ⏸ ▶️ ☰ &a…...
VBS脚本搞定,快速批量提取一堆Excel文件中的数据
1.需求诞生 小王就职于一家国有大型企业,工作业务十分繁忙,在处理企业某业务数据时,需要从上千个Excel文件中提取某一单元格位置的数据,并整理到另一个Excel文件。要说是这样的Excel文件仅有几个或者十几个也还好,手动…...

大数据分析案例-基于SVM支持向量机算法构建手机价格分类预测模型
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...

WPF 滑动条样式
效果图: 浅色: 深色: 滑动条部分代码: <Style x:Key"RepeatButtonTransparent" TargetType"{x:Type RepeatButton}"><Setter Property"OverridesDefaultStyle" Value"true"/&g…...

论文设计任务书学习文档|基于Web的个性化简历职位推荐系统的设计与实现
文章目录 论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现1、论文(设计)的主要任务及目标2、论文(设计)的主要内容3、论文(设计)的基本要求4、进度安排论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现 1、论文(设计)的主要任务及目标…...

Win11系统安装安卓子系统教程
随着Win11系统的不断普及,以及硬件设备的更新换代,我相信很多同学都已经更新并使用到了最新的Win11系统。那么,Win11系统最受期待的功能“Windows Subsystem for Android”(简称WSA),即《安卓子系统》。他可…...

Python实现双向链表:从基础到应用
一、引言 双向链表是一种比单向链表更复杂的数据结构,每个节点除了包含数据和指向下一个节点的指针外,还包含一个指向前一个节点的指针。这种结构使得我们可以从链表的任何节点开始,向前或向后遍历链表。 目录 一、引言 二、节点定义 三、…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...