C++之类和对象(上)
目录
1.面向过程和面向对象初步认识
2.类的引入
3.类的定义
4.类的访问限定符及封装
4.1访问限定符
4.2 类的两种定义方式
第一种:
第二种:
4.3封装
5.类的实例化
6.类对象模型
1.面向过程和面向对象初步认识
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
2.类的引入
C语言中,结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数
struct stack
{int* a;int size;int capacity;
};
void Init()
{//...
}
void Destory()
{//...
}
int main()
{stack st;return 0;
}
这是正常情况下我们去建立一个栈的代码(省略了一部分)
在C++中,我们则是优化使用了类去实现栈,更加便捷
我们可以直接去定义新的栈
struct stack st1;
stack st2;
同时,我们还可以把我们所需要的栈的函数去定义到我们的结构体中
using namespace std;
struct stack
{int* a;int size;int capacity;void Init(int n = 4){a = (int*)malloc(sizeof(int) * n);if (a == nullptr){perror("malloc fail");return;}//...size = 0;capacity = n;}void Destory(){//...}void Push(int x){a[size++] = x;}
};
int main()
{//stack st;stack st1;st1.Init();st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);return 0;
}
如以上代码
这里的st1就是一个对象
3.类的定义
class className
{// 类体:由成员函数和成员变量组成}; // 一定要注意后面的分号
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。 类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。
我们可以简单定义一个日期,也就是年月日
class Data
{
private:int _year;int _month;int _day;
};
C++中一般在定义变量中都会在前边加上一个_去区分
然后我们再加一个函数去令他完善一下
class Data
{
public:void Init(int year = 2024,int month = 1,int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{Data d1;d1.Init(2024, 4, 6);return 0;
}
这样我们就完成了
这里就会有人问了,这里的public和private又是什么?
这里就涉及到我们另外一个知识点:类的访问限定符及封装
4.类的访问限定符及封装
4.1访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其 接口提供给外部的用户使用。

- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
所以用通俗易懂的话去讲就是:
private里面的基本都是存储的变量,无法去直接访问并改变,publi里面的存储的是函数,可以直接去访问并做出一定的编译
所以理解这些后,刚才的日期代码才能够去充分理解
class Data
{
public:void Init(int year = 2024,int month = 1,int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{Data d1;d1.Init(2024, 4, 6);return 0;
}
4.2 类的两种定义方式
在C++中定义类时,主要有两种方式:在单个文件中定义整个类(包括成员变量和成员函数),或者将类的声明和定义分别放在不同的文件中(声明定义分离)。下面将详细讨论这两种方式
第一种:
声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理
using namespace std;
struct stack
{int* a;int size;int capacity;void Init(int n = 4){a = (int*)malloc(sizeof(int) * n);if (a == nullptr){perror("malloc fail");return;}//...size = 0;capacity = n;}void Destory(){//...}void Push(int x){a[size++] = x;}
};
第二种:
类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
.h文件:
class stack
{
public:void Init(int n = 4);void Push(int x);
private:int* a;int size;int capacity;
};
.cpp文件:
void stack::Init(int n)
{a = (int*)malloc(sizeof(int) * n);if (a == nullptr){perror("malloc fail");return;}capacity = n;size = 0;
}
void stack::Push(int x)
{//...
}
在.cpp文件中,我们不要直接去定义Init,如果直接定义会报错

所以要在Init前边加上stack::去表明,这是这个是属于stack类域的(也就是类的作用域)
同时也要注意:传参时,我们只需要在头文件中去设置半参省或者全参省,在源文件.cpp中只需要传递所需要的参数即可,也就是int n
类的作用域也是影响了搜索规则,比如下面两个类,栈和队列都有init和push函数:
class stack
{
public:void Init(int n = 4);void Push(int x);
};
class queue
{
public:void Push(int x);
};
如果没有域的存在,就会出现冲突
所以,类本身就是一种域
4.3封装
面向对象的三大特性:封装、继承、多态
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互。
封装本质上是一种管理:我们如何管理兵马俑呢?比如如果什么都不管,兵马俑就被随意破坏了。那么我们 首先建了一座房子把兵马俑给封装起来。但是我们目的全封装起来,不让别人看。所以我们开放了售票通 道,可以买票突破封装在合理的监管机制下进去参观。类也是一样,我们使用类数据和方法都封装到一下。 不想给别人看到的,我们使用protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访 问。所以封装本质是一种管理。
封装的优势:
-
安全性:通过隐藏其内部状态,对象不会因为外部代码的直接访问而处于不一致的状态
-
简化接口:对象提供的公共方法可以是简单的接口,使用者无需了解实现细节即可使用对象
-
降低复杂性:将数据和操作数据的代码封装在一起有助于减少系统的复杂性
-
可维护性和可扩展性:封装使得修改和增加功能变得简单,因为修改的影响局限于单个对象内部,不会波及整个系统
-
重用性:通过封装,可以使对象更加通用,易于在不同场景下复用
5.类的实例化
用类类型创建对象的过程,称为类的实例化
class Data
{
public:void Init(int year = 2024,int month = 1,int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
思考一下,在这个代码中,int _year; int _month; int _day;这是声明还是定义呢?
定义和声明的本质区别是是否开辟一块空间
class Data
{
public:void Init(int year = 2024,int month = 1,int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{Data d1;//d1.Init(2024, 4, 6);return 0;
}
这里的Data d1;这才是定义

在这里,我们不能直接对 Data::Init进行直接访问,也无法对year,month以及day进行直接访问,因为这里的year,month以及day只是声明不是定义

但是我们可以对d1的变量进行访问
而这一步,Data d1;这就是类的实例化
类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什 么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占 用物理空间

6.类对象模型
类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大 小?
class Data
{
public:void Init(int year = 2024,int month = 1,int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};
上面类的大小是多少字节?
结构体内存对齐规则:
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。 VS中默认的对齐数为8
- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
我们利用sizeof计算一下
12字节
这个12字节怎么算的呢?
如果去除掉函数的话,一共3个int元素变量,这样的话确实是12字节
是不是函数不算呢?
我们去除一下函数看一看

还是12字节
所以由此可知,这与类成员的存储结构有关,与函数无关
这里定义了一个d1,我们在定义一个d2看一看

转到编译码中可以看到,两个函数的地址相同
所以猜测一下,类的对象模型应该是什么样的???
猜测一:对象中包含类的各个成员

缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。
猜测二:只保存成员变量,成员函数存放在公共的代码段


每个成员的函数的地址都是一样的,在公共区域存放函数的代码更加的合理
class A2 {
public:void f2() {}
};
看一下,这个类的大小是多少?

大小为一
为什么呢?
原因是:
在C++中,类的大小是由其数据成员决定的。如果一个类没有数据成员,其大小通常不会是0,因为语言标准确保每个对象都必须有一个独一无二的地址,以便能够区分不同的对象。即使一个类没有任何数据成员,编译器也会给对象分配至少一个字节的大小,以保证对象有独立的地址
所以对于A2这个类域,虽然里面没有数据成员,只有一个函数f2,但编译器也会给一个字节的空间
class fun {
public:void Print(){cout << "被调用" << endl;}
};
int main()
{fun a1;fun* p1 = &a1;p1->Print();fun* p = nullptr;p->Print();return 0;
}
再看一下这个代码
把p设置为空指针,这里的print还会被调用吗?

最终结果仍是被调用了
为什么呢?
这里的
Printf函数并不在指针指向的空间里面,而这里的p1,p2指向的是对象,对象里面没有函数的地址,虽然有箭头,但是并没有进行解引用

相关文章:
C++之类和对象(上)
目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 4.1访问限定符 4.2 类的两种定义方式 第一种: 第二种: 4.3封装 5.类的实例化 6.类对象模型 1.面向过程和面向对象初步认识 C语言是面向过程的,…...
Linux 测试磁盘读写速度
1、先熟悉两个特殊的设备: (1)/dev/null:回收站、无底洞。 (2)/dev/zero:产生字符。 2、测试磁盘写能力 time dd if/dev/zero of/testw.dbf bs4k count100000 因为/dev//zero是一个伪设备…...
【YOLOv8】Yolov5和Yolov8网络结构的分析与对比
目录 一 YOLOv5 二 YOLOv8 yolo通常采用backbone-neck-head的网络结构。 Backbone 主要负责从输入图像中提取高层次的语义特征,常包含多个卷积层和池化层,构建了一个深层次的特征提取器。Neck通常用来进一步整合与调整backbone提取的特征,有利于将不同…...
无人机低空数字摄影测量系统
一、 系统概述 系统完全基于IDL设计实现,包括界面布局到人机交互再到底层核心函数功能。整体设计框架基于数字摄影测量的专业处理流程,实现了数据输入、数据预处理、影像信息检测、空间定向、地形三维建模、专题信息提取、成果输出与更新等功能。同时为…...
Disk Drill Enterprise for Mac v5.5.1515数据恢复软件中文版
Disk Drill 是 Mac 操作系统固有的Mac数据恢复软件:使用 Recovery Vault 轻松保护文件免遭意外删除,并从 Mac 磁盘恢复丢失的数据。支持大多数存储设备,文件类型和文件系统。 软件下载:Disk Drill Enterprise for Mac v5.5.1515激…...
day55 最长递增子序列 最长连续递增子序列 最长重复子数组
题目1 300 最长递增子序列 题目链接 300 最长递增子序列 题意 找到整数数组nums的最长严格递增子序列的长度(子序列并不改变原始的顺序,但是可以删除元素) 动态规划 动规五部曲 1)dp数组及下标i的含义 dp[i] 表示以nums[i…...
使用Springboot配置生产者、消费者RabbitMQ?
生产者服务 1、引入依赖以及配置rabbitmq 此时我们通过使用springboot来快速搭建一个生产者服务 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> applica…...
代码随想录算法训练营第46天|139.单词拆分、多重背包问题
139.单词拆分 题目链接:单词拆分 题目描述:给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 **注意:**不要求字典中出现的单词全部都使用,并且字典中的单词…...
数组与伪数组的区别
大家都知道,在js中使用 document.querySelectorAll(选择器)获取到的为该选择器能选择到的所有元素组成的伪数组,所谓伪数组,就是外表和数组一样,能够使用索引遍历,但本质是对象。 数组与伪数组之间的区别&…...
Java集合List
List特有方法 经典多态写法 // 经典的多态写法 List<String> list new ArrayList<>();常用API:增删改查 // 添加元素 list.add("Java"); // 添加元素到指定位置 list.add(0, "Python");// 获取元素 String s list.get(0);// 修改…...
elasticsearch基础命令
1 字段分词分析: GET /store_info_data/_analyze {"field": "storeName","text":"20pilapala0" }2 精确查找,去除评分 GET /store_info_data/_search {"query": {"constant_score": {"filter": {&quo…...
Capture One 23 Enterprise for Mac中文版 全面的图像处理工具
Capture One 23 Enterprise for Mac中文版一款专业的图像编辑和管理软件,具备强大的功能和工具,适用于摄影师、摄影工作室和专业用户。 软件下载:Capture One 23 Enterprise for Mac中文版下载 该软件为用户提供了全面的图像处理工具…...
Qt案例 通过调用Setupapi.h库实现对设备管理器中设备默认驱动的备份
参考腾讯电脑管家-软件市场中的驱动备份专家写的一个驱动备份软件案例,学习Setupapi.h库中的函数使用.通过Setupapi.h库读取设备管理器中安装的设备获取安装的驱动列表,通过bit7z库备份驱动目录下的所有文件. 目录导读 实现效果相关内容示例获取SP_DRVIN…...
如何理解JVM
JVM(Java虚拟机)是Java程序的运行环境,它是Java技术的核心组成部分之一。理解JVM涉及到以下几个方面的内容: 1. **虚拟机概念**:虚拟机是一种软件实体,它在物理计算机上模拟出一个计算机系统,使…...
第十四讲:C语言字符函数和字符串函数
目录 1. 字符分类函数 2、字符转换函数 3. strlen的使⽤和模拟实现 4. strcpy 的使⽤和模拟实现 5. strcat 的使⽤和模拟实现 6. strcmp 的使⽤和模拟实现 7. strncpy 函数的使⽤ 8. strncat 函数的使⽤ 9. strncmp函数的使⽤ 10. strstr 的使⽤和模拟实现 11. strt…...
华为海思2024春招数字芯片岗机试题(共9套)
huawei海思2024春招数字芯片岗机试题(共9套,有答案和解析,答案非官方,未仔细校正,仅供参考)(WX:didadidadidida313,加我备注:CSDN huawei数字题目,谢绝白嫖哈)…...
分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测
分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测 目录 分类预测 | Matlab实现KPCA-IDBO-LSSVM基于核主成分分析和改进蜣螂优化算法优化最小二乘支持向量机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述…...
与机器对话:ChatGPT 和 AI 语言模型的奇妙故事
原文:Talking to Machines: The Fascinating Story of ChatGPT and AI Language Models 译者:飞龙 协议:CC BY-NC-SA 4.0 从 ELIZA 到 ChatGPT:会话式人工智能的简史 会话式人工智能是人工智能(AI)的一个分…...
概率论基础——拉格朗日乘数法
概率论基础——拉格朗日乘数法 概率论是机器学习和优化领域的重要基础之一,而拉格朗日乘数法与KKT条件是解决优化问题中约束条件的重要工具。本文将简单介绍拉格朗日乘数法的基本概念、应用以及如何用Python实现算法。 1. 基本概念 拉格朗日乘数法是一种用来求解…...
[xboard]real6410-6.2 移植kernel网络驱动
文章目录 硬件电路软件配置问题1问题2问题3问题4功能测试硬件电路 核心板,使用DM9000A [图片] 软件配置 问题1 / # / # ifconfig ifconfig: /proc/net/dev: No such file or directory ifconfig: socket: Fun...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
