C++类与对象 (上)
目录
前言:
类和对象的理解
类的引入
类的定义与使用方式
访问限定符
类的两种定义方式
成员变量的命名规则
类的作用域
类的实例化
类对象模型
计算类对象的大小
类对象的存储方式
this指针
前言:
- C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题;
- C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成;
类和对象的理解
类是一个抽象的概念,描述了一类对象的共同属性和行为;
对象是类的具体化,它是类的实例,具有类中定义的属性和行为;
在C++中,类通常由数据成员和成员函数组成,数据成员是类的属性,它们描述了对象的状态,成员函数是类的行为,它们描述了对象可以执行的操作,对象的创建是通过类的实例化来完成的,当程序需要使用类时,可以通过创建类的对象来使用类的属性和行为;
举例如下:
将“汽车”看作一个类,在这个类中定义了汽车的属性和行为,比如颜色、品牌、速度等属性,以及加速、刹车、转弯等行为;当我们要描述具体一辆汽车时,就需要创建一个该类的对象,并根据需要设置其相应的属性值或对其进行行为操作;
类的引入
由于C++兼容C语言中struct的所有用法,同时C++对关键字struct进行了升级,将struct升级为类;
- struct 类名 (类名即为变量类型)
//c语言
struct Stack
{int* a;int top;int capacity;
};
int main()
{//Stack s1; //C语言 ---> 未定义的标识符struct Stack s1;//只能采取带上struct关键字定义变量return 0;
}
//c++
struct Stack
{int* a;int top;int capacity;
};
int main()
{Stack s1;//可直接采取这种方案定义变量,不需要加上struct的关键字return 0;
}
//c语言定义链表结点
struct ListNode
{//ListNode* next;//C语言 ---> 未定义的标识符struct ListNode* next;int val;
};
//c++定义链表结点
struct ListNode
{ListNode* next;//编译通过int val;
};
- C++结构体中可以定义函数;
//c++ 类里面可以定义函数
struct Stack
{int* a;int top;int capacity;//初始化栈void Init(){a = 0;top = 0;capacity = 0;}
};
C++用关键字 class 代替 struct;
类的定义与使用方式
class 类名
{//类体: 由成员变量与成员函数组成}; //此处分号不可省略
类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或成员函数;
访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用;

访问限定符说明:
- public修饰的成员在类外可以直接被访问 ;
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止;
- 如果后面没有访问限定符,作用域就到 } 即类结束;
- class的默认访问权限为private,struct默认访问权限为public(因为struct要兼容C)
class Stack
{
private:int* a;int top;//a,top,capacity--->成员变量私有int capacity;//private的作用域从private开始到public,若没有public,直接到类结束;//由于class的默认访问权限为私有,省略掉private,三个成员变量依旧私有
public://初始化栈void Init()// Init()函数公有{a = 0; top = 0;capacity = 0;}
}; //类结束
类定义的惯例:成员变量私有,成员函数公有;
class Stack
{
public:int* a;int top;int capacity;//初始化栈void Init(){a = 0; top = -1;capacity = 0;}//空栈的判断bool StackEmpty(){return (top == -1);}
};
int main()
{Stack s1;s1.Init();//判断方式1:空栈, 若top=0,表示指向栈顶元素的下一个位置;// 空栈, 若top=-1,表示指向栈顶元素的位置;//栈的定义方式不同,如下判断方法可能导致出错;if (s1.top==0)//判断方式2:采取访问成员函数进行判断,直接调用判空函数,不会出错if (!s1.StackEmpty()){}//如上就是成员变量私有,成员函数公有的原因return 0;
}
类的两种定义方式
定义方式1:类的声明放在.h文件中,成员函数定义放在.cpp文件中;
(注:成员函数名前加 类名 ::)
定义方式2:声明和定义全部放在类体中;
(注:成员函数如果在类中定义,编译器可能会将成员函数当成内联函数处理)
成员变量的命名规则
class Date
{
public:void Init(int year,int month,int day){// 这里的year到底是成员变量,还是函数形参?year = year;//局部优先,year为函数形参//局部优先是指在函数内部创建了一个和全局变量同名的局部变量时;//函数内部对该变量的操作会优先作用于局部变量,而不会改变全局变量的值}
private:int year;int month;int day;
};
为了避免如上情形,C++采用成员变量前加 _
class Date
{
public:void Init(int year,int month,int day){_year = year;}
private:int _year;int _month;int _day;//year month day成员变量前加 _
};
类的作用域
类 定义了一个 新的作用域, 类的所有成员都在类的作用域中;在 类体外定义成员时,需要使用 ::作用域限定符指明成员属于哪个 类域;c++中由{ }所定义的皆为作用域;
class Stack
{//变量的声明,没有在内存中开辟空间int* a;int top;int capacity;
public:void Init();bool StackEmpty();
};
//需要指定Init()函数属于Stack类域
void Stack::Init()
{a = 0;top = 0;capacity = 0;
}
类的实例化
用类的类型创建对象的过程,称为类的实例化;
- 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;
- 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
class Date
{
public:void Init(int year,int month,int day){_year = year;}int _year;int _month;int _day;
};
int main()
{Date::_year = 2023;//编译错误,成员变量为声明,没有开辟内存空间存储;// Date d; d.year=2023 //正确做法return 0;
}
//Date类是没有空间的,只有Date类实例化出的对象才有具体的年份
3. 类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间;
类对象模型
类对象模型:类对象模型是指将类的成员函数和成员变量存储在一起的方式,这种方式将类的成员函数和成员变量封装在一个对象中,通过该对象来访问类的成员;
计算类对象的大小
# include <iostream>
using namespace std;
class Date
{
public:void Init(int year,int month,int day){_year = year;}int _year;int _month;int _day;
};
int main()
{Date d;cout << sizeof(d) << endl;return 0;
}
问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?
类对象的存储方式
类对象的存储方式:
对象中只保存成员变量,成员函数存放在公共代码段,这种方式将类的成员变量存储在对象中,而将成员函数存放在公共代码段中,通过对象来访问类的成员函数;
结论:一个类的对象大小,实际就是该类中”成员变量”之和,注意考虑内存对齐 ;
空类的大小:空类的大小为1字节;即使一个类没有任何成员变量和成员函数,它也会占用1字节的内存空间;
空的结构体大小:空的结构体大小为0字节,与空类不同,空的结构体不占用任何内存空间;
//类中仅有成员函数--->1byte
//对象中无成员函数
class B
{
public:void f2() {}
};
int main()
{B b;cout << sizeof(b) << endl;return 0;
}
//空类的大小 ---> 1byte
//无成员变量的类开辟1个字节,该字节不存储有效数据
//标识定义的对象存在过
class C
{};
int main()
{C c;cout << sizeof(c) << endl;return 0;
}
this指针
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;//年int _month;//月int _day;//日
};
int main()
{Date d1, d2;d1.Init(2023, 12, 17);d2.Init(2023, 12, 16);d1.Print();d2.Print();return 0;
}
运行结果:
Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,d1调用的Print()函数与d2调用的Print()函数相同,那当d1调用Print()函数时,该函数是如何知道应该显示d1对象,而不是显示d2对象呢?
C++ 中通过引入 this指针 解决该问题,即: C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问;只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成 ;

this指针的特性:
- this指针的类型:类型* const ,由于const修饰this,this指针不允许被修改;
- 只能在“成员函数”的内部使用 (不能显示的写实参和形参,但是可以在类中显示的使用);
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针;
- this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递 ;
相关文章:

C++类与对象 (上)
目录 前言: 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言: C语言是面向过程的,关注的是过…...

no module named ‘xxx‘
目录结构如下 我想在GCNmodel的model里引入layers的GraphConvolution:from GCNmodel.layers import GraphConvolution,但这样却报错no module named GCNmodel,而且用from layers import GraphConvolution也不行。然后用sys.path.appen(xxx)…...
Go实现MapReduce
背景 当谈到处理大规模数据集时,MapReduce是一种备受欢迎的编程模型。它最初由Google开发,用于并行处理大规模数据以提取有价值的信息。MapReduce模型将大规模数据集分解成小块,然后对这些小块进行映射和归约操作,最终产生有用的…...
Axure的交互样式和情形
Axure的交互样式和情形 交互样式 Axure是一个流行的原型设计工具,它允许您创建交互式原型,模拟应用程序或网站的功能和用户界面。在Axure中,您可以设置各种交互样式来使原型更加生动和真实。 链接触发器:通过给一个元素添加链接…...
Mybatis在新增某个数据后,如何获取新增数据的id
在某些业务中,我们在新增一条数据之后,需要拿到这条数据的id来对这条数据进行后续的一个操作,如何拿取id呢? 使用的是<insert> 中的useGeneratedKeys 和 keyProperty 两个属性 1.在Mybatis Mapper文件中添加属性 “useGene…...

12.4~12.14概率论复习与相应理解(学习、复习、备考概率论,这一篇就够了)
未分配的题目 概率计算(一些转换公式与全概率公式)与实际概率 ,贝叶斯 一些转换公式 相关性质计算 常规,公式的COV与P 复习相关公式 计算出新表达式的均值,方差,再套正态分布的公式 COV的运算性质 如…...

关于多重背包的笔记
多重背包可以看作01背包的拓展, 01背包是选或者不选。多重背包是选0个一直到选s个。 for (int i 1; i < n; i) {for (int j m; j > w[i]; --j){f[j] max(f[j], f[j - 1*w[i]] 1*v[i], f[j - 2*w[i]] 2*v[i],...f[j - s*w[i]] s*v[i]);} } 由上述伪代码…...
如何使用 Java 的反射
如何使用 Java 的反射? 通过一个全限类名创建一个对象 Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver 类已经被加载到 jvm 中,并且完成了类的初始化工作就行了 类名.class; 获取 Class<?> clz 对象对…...

PLC-Recorder V3 修改服务器和客户端通讯端口的方法
PLC-Recorder V3是服务器和客户端的架构,他们之间用TCP通讯。如果客户端无法与服务器建立连接(重启也无效,并且确保没有老版本的PLC-Recorder在运行),则可能是端口被占用了。这时候需要修改他们之间的通讯端口…...

libevent服务GET/POST的简单使用
目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信,比较常用的使用POST和GET方式…...

MySQL 系列:注意 ORDER 和 LIMIT 联合使用的陷阱
文章目录 前言背后的原因ORDER BY 排序列存在相同值时返回顺序是不固定的LIMIT 和 ORDER BY 联合使用时的行为ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引 如何解决其它说明个人简介 前言 不知道大家在在分页查询中有没有遇到过这个问题,分页查…...

通过实例理解OAuth2授权
在之前的《通过实例理解Go Web身份认证的几种方式[1]》和《通过实例理解Web应用授权的几种方式[2]》两篇文章中,我们对Web应用身份认证(AuthN)和授权(AuthZ)的几种方式做了介绍并配以实例增强理解。 在现实世界中,还有一大类的认证与授权是在前面的文章中…...

MATLAB2022安装下载教程
安装包需从夸克网盘自取: 链接:https://pan.quark.cn/s/373ffc9213a1 提取码:N7PW 1.将安装包解压 2.以管理员的身份运行文件夹中的setup文件 3.点击高级选项--->我有文件安装密钥 4. 选择【是】,进入下一步 5.输入密钥 0532…...
从零开始搭建Go语言开发环境
https://www.liwenzhou.com/posts/Go/install_go_dev/ “go 命令现在默认在模块感知模式下构建包,即使没有 go.mod 存在也是如此。 “您可以将 GO111MODULE 设置为 auto,仅当当前目录或任何父目录中存在 go.mod 文件时,才能启用模块感知模式…...

vite+vue3+ts+tsx+ant-design-vue项目框架搭建
参与公司项目开发一段时间了,项目用到了很多新的技术(vite,vue3,ts等等),但是框架都是别人搭好的,然后就想说如果是自己的话,会从零搭建一个吗,于是就有了这篇文章。 目录 一、涉及到的相关依…...

【5G PHY】5G小区类型、小区组和小区节点的概念介绍
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…...

创建个人网站(一)从零开始配置环境,搭建项目
目录 前言配置环境前端后端遇到的问题1.安装了nvm和node,vscode没反应2.安装完脚手架之后vue指令不存在 vscode插件(以后遇到好的会添进去) 前言 从刚开始学前端的html直到现在前后端都有在开发,我一直都有一个想法,就…...
fripside - promise lrc
[ti:promise] [ed:2] [rt:20] [ml:0|0] [00:05.172]words:Satoshi Yaginuma, Shinichiro Yamashita [00:09.664]music&arrangement:Satoshi Yaginuma, Shigetoshi Yamada [00:14.565]PCゲーム「ENGAGE LINKS」 (Alcot) エンディングテーマ [00:20.000] [00:46.442]朝の陽射…...
网络连接和协议
网络连接是通过一系列协议来实现的,其中TCP/IP协议和HTTP协议是其中两个关键的协议。 1. **TCP/IP协议:** - TCP/IP(Transmission Control Protocol/Internet Protocol)是一组用于在互联网上传输数据的协议。它是一个层次化的…...

MySQL数据库,表的增量备份与恢复
1. 从物理与逻辑的角度 数据库备份可以分为物理备份和逻辑备份。物理备份是对数据库操作系统的物理文件(如数据 文件,日志文件等)的备份。这种类型的备份适用于在出现问题时需要快速恢复的大型重要数据库。 物理备份又可以分为冷备份…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...