当前位置: 首页 > news >正文

类于对象(上)--- 类的定义、访问限定符、计算类和对象的大小、this指针

        在本篇中将会介绍一个很重要和很基础的Cpp知识——类和对象。对于类和对象的篇目将会有三篇,本篇是基础篇,将会介绍类的定义、类的访问限定符符和封装、计算类和对象的大小、以及类的 this 指针。目录如下:

目录

1. 关于类

1.1 类的定义

2 类的访问限定符及封装

 1.3 类的实例化——对象

3 类与对象的空间大小

3.1 结构体内存对齐规则

4. this 指针

4.1 this 指针的特性 

1. 关于类

        首先需要先区分两个名词:面向对象面向过程。面向对象的思想主要发挥在Cpp中,而面向过程的思想主要发挥在C语言中。

        面向过程:关注过程,分析问题的每一个步骤,然后提高函数对每一个步骤都逐一解决。就好像点外卖,首先我需要打开外卖app,然后决定要吃什么,然后找到对应的店铺,接着下单,等待到餐以及去取餐。

        面向对象:关注的是对象,将一件事情拆分为不同的对象,依靠对象之间的交互完成。比如点外卖分为了三个对象:我、外卖员、商家。我负责下单,外卖员负责送外卖,商家负责做餐。将一件事情先分给不同的对象,然后让对象之间相互配合完成这件事情。

1.1 类的定义

        在C++的类,与C语言中的结构体很相似,都用来同一定义我们的自定义类型变量。但是在Cpp中的类不仅仅可以定义成员变量,还可以定义成员函数

        对于类的定义如下:

class ClassNmae {//成员函数 and 成员变量
};struct ClassName {//成员函数 and 成员变量
};

        其中 class、struct定义类的关键字,ClassName为类的名字,{} 中为类的主体注意类定义结束时后面分号不能省略。(对于 class 和 struct 都可以用于定义类,比较常用的是 class,将会在下文中介绍这两者的区别)。
        对于类体中内容称为类的成员:类中的变量称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数

        对于成员函数的声明定义方法:1.声明和定义放在类体中;2.声明与定义分离。

        1.声明与定义放在类体中:

class Stack {
public:void Init() {_a = (int*)malloc(sizeof(int) * 4);_capacity = 4;_top = 0;}void Push(int x) {if (_top == _capacity) {int newCapacity = 2 * _capacity;int* tmp = (int*)realloc(_a, sizeof(int) * newCapacity);if (tmp == nullptr) {perror("realloc failed:");exit(1);}_a = tmp;_capacity = newCapacity;}_a[_top++] = x;}void Pop() {assert(_top != 0);_top--;}//...
private:int* _a;int _top;int _capacity;
};

        2.声明与定义分离:

// Stack.h
class Stack {
public:void Init();void Push(int x);void Pop();//...
private:int* _a;int _top;int _capacity;
};// Stack.c
void Stack::Push(int x) {if (_top == _capacity) {int newCapacity = 2 * _capacity;int* tmp = (int*)realloc(_a, sizeof(int) * newCapacity);if (tmp == nullptr) {perror("realloc failed:");exit(1);}_a = tmp;_capacity = newCapacity;}_a[_top++] = x;
}void Stack::Init() {_a = (int*)malloc(sizeof(int) * 4);_capacity = 4;_top = 0;
}void Stack::Pop() {assert(_top != 0);_top--;
}

        如上就是成员函数的声明定义方法,通常更推荐使用第二种,将声明与定义分离,不过需要定义与声明分离之后的定义形式。

2 类的访问限定符及封装

        Cpp实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用

        访问限定符:public(公有)、private(私有)、protected(保护)。

        访问限定符说明:

        1.public修饰的成员在类外可以直接被访问。

        2.protected、private修饰的成员在类外不能直接被访问。

        3.访问权限的作用域从该访问限定符出现的位置开始到下一个访问限定符出现为止,若后面没有访问限定符,则到 } 结束。

        4.class 的默认访问权限为 private,struct 为public

        面向对象的三大特性:封装、继承、多态。本篇将主要介绍封装。

        封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互。(简单来说,就是将类中的部分变量进行隐藏(使用private修饰),仅仅放出一些变量(public修饰)用于和类外的变量进行交互)。

        如下:

        图中显示,并不能直接访问由 private 修饰的变量,只能通过由 public 修饰的成员函数来进行对对象进行操作。

        类的作用域,我们既然将类进行了封装,那么对于类就存在一个新的作用域。类的所有成员都在类的作用域中。类外定义成员时,需要使用 “ : : ” 作用域操作符指明成员属于哪一个类域。

 1.3 类的实例化——对象

        用类类型创建对象的过程叫做类的实例化

        类是对对象进行描述的,类似于一个模板一样的东西,我们可以看见一个用类创建出来的对象有哪些成员变量和成员函数。对于类来说,并不占有空间。

        所以一个类可以实例化多个对象,实例化出来的对象占据实际的物理空间,存储类的成员。如下图:

        使用 Stack 类定义出两个对象。

3 类与对象的空间大小

        在C语言中,我们计算时间结构体的大小使用的是内存对齐规则,那么我们在Cpp中该使用什么样的办法计算一个类或对象所占空间大小呢?我们在Cpp中同样使用的是内存对齐规则,不过Cpp中的内存对齐规则和C语言中的内存对齐规则存在些许不同,比如在Cpp中不仅仅存在成员变量,还存在成员函数,成员函数的大小该如何计算

        我们先计算一下对于以上 Stack 的一个对象的大小:

        如上图所示,计算出来的结果显示为16,计算的大小也刚好是 Stack 中成员变量的大小,并没有计算成员函数的大小。说明在Cpp中的内存对齐规则中,并不会计算成员函数的大小

        对于Cpp中的成员函数来说,并不是每个实例化的对象都存在独立空间的成员函数成员函数是所有同样类的对象的共享成员函数成员函数的存放在一个公共代码区

        但是若一个类只存在成员函数而没有成员变量,或则成员函数和成员变量都没有呢,那这个类的大小是0吗?如下:

        如上图所示,当类只存在成员函数而没有成员变量时,计算出来的空间为1。那是因为在Cpp的标准中,编译器给空类一个字节来唯一标识这个类的对象。

3.1 结构体内存对齐规则

        1. 第一个成员在与结构体偏移量为0的地址处。

        2. 其他成员变量要对齐到某个数字的整数倍的地址处。(注:对齐数 = 编译器默认的一个对齐数 与 该成员变量大小的较小值)

        3. 结构体的总大小:最大对齐数的整数倍(所有成员的类型的最大者和编译器默认对齐数的较小值)

        4. 若嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。

4. this 指针

        如下图,我们在成员函数中的变量名前增加了一个 this 指针:

        为什么我们加入了一个 this 指针,我们的程序还能正确的运行呢?

        这和我们调用成员函数相关,当我们在调用成员函数时,我们并不需要将成员变量传入成员函数中,而是直接调用(如图中的 Print 函数),成员函数就可以根据对应的成员变量而调用。这是因为:

        Cpp编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数 this ,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

4.1 this 指针的特性 

        成员函数中的 this 指针存在一些特性以及使用时的细节,将在以下给出。       

        1. this 指针的类型:类* const,即成员函数中,我们不能给 this 指针赋值。

        2. this 指针只能存在于成员函数之中,并不能在成员函数外使用。

        3. this 指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this 形参。所以对象中不存在 this 指针。

        4. this 指针是“成员函数”第一个隐含的指针形参,一般情况下由exc寄存器自动传递,不需要由用户来操作。

        可以理解这两个函数是相同的,但是并不能写成第二种,第二种会报错。

        this 指针的使用细节如下:

        如上图所示,当我们在一个类中定义了两个 Print 函数,但是真正运行起来时,只有 Print1 可以正常的运行,而 Print2 并不能正常的运行。这是因为:

        当我们执行 Print1 时,成员函数中的 this 指针直接拷贝了 nullptr,然后执行 Print1 中的语句。但是当执行 Print2 时,this 指针拷贝了 nullptr,然后在接下来的语句中直接调用了 nullptr 处的 _a 变量,此处的变量并没有被开发,所以运行起来会报错。

相关文章:

类于对象(上)--- 类的定义、访问限定符、计算类和对象的大小、this指针

在本篇中将会介绍一个很重要和很基础的Cpp知识——类和对象。对于类和对象的篇目将会有三篇,本篇是基础篇,将会介绍类的定义、类的访问限定符符和封装、计算类和对象的大小、以及类的 this 指针。目录如下: 目录 1. 关于类 1.1 类的定义 2 类…...

提升交付效率:Booking.com 金融技术团队的成功实践

Booking.com 金融技术业务部门的团队对其平台的后端和前端实施了一系列改进措施,并通过 DORA 指标将交付性能提高了一倍。此外,还使用了微前端 (MFE) 模式,将单体 FE 应用程序分解为多个可单独部署的分解应用程序。 2022 年年中,B…...

【消息队列开发】 实现ConsumerManager类——消费消息的核心逻辑

文章目录 🍃前言🌴扫描线程的实现🌲实现消费消息🌳实现addConsumer()方法🎋VirtualHost类订阅消息的完善⭕总结 🍃前言 本次开发目标 实现消费消息的核心逻辑 🌴扫描线程的实现 我们先给Cons…...

【Three.js】使用精灵图Sprite创建面朝相机的文本标注

目录 🐝前言 🐝canvas创建文字 🐝将canvas作为纹理贴图加载到sprite中 🐝封装方法 🐝前言 在Three.js中精灵Sprite是一个总是面朝摄像机的平面,它通常和纹理贴图结合使用,贴图可以是一张图…...

C++中的类模板

C中的类模板 类模板 类模板在C中是一种非常强大的工具,它允许程序员编写与数据类型无关的代码。简单来说,类模板允许你定义一个蓝图,这个蓝图可以用来生成具体类型的类。使用类模板可以提高代码的复用性,减少重复代码&#xff0…...

【每日一题】好子数组的最大分数

Tag 【单调栈】【暴力枚举】【数组】【2024-03-19】 题目来源 1793. 好子数组的最大分数 解题思路 本题和 84. 柱状图中最大的矩形 一样,计算的都是最大矩形的面积。只不过多了一个约束:矩形必须包含下标 k。 以下的方法一和方法二是 84. 柱状图中最…...

Vue2(七):超详细vue开发环境搭建(win7),nodejs下载与安装,安装淘宝镜像(报错已解决),配置脚手架

一、安装node.js 本来想粗略写一下的,但是搭建脚手架的时候,遇到了很多问题,浪费快两天时间,记录一下自己的解决办法希望对你们有帮助! 1.下载nodejs 安装包下载链接【CNPM Binaries Mirror】 下载我划线的这个&am…...

【Web】记录CISCN 2021 总决赛 ezj4va题目复现——AspectJWeaver

目录 前言 原理分析 step 0 step 1 EXP 前文:【Web】浅聊Java反序列化之AspectJWeaver——任意文件写入-CSDN博客 前言 这就是当年传说中的零解题嘛😭,快做🤮了 有了之前的经验,思路顺挺快的,中间不…...

视频技术1:使用ABLMediaServer推流rtsp

ABLMediaServer定位是高性能、高稳定、开箱即用、商用级别的流媒体服务器 下边展示了如何把1个mp3作为输入源,转换为rtsp流的过程。 作用:用rtsp模拟摄像头的视频流 1、启动ABLMediaServer ABLMediaServer-2024-03-13\WinX64\ABLMediaServer.exe 配…...

HTML5+CSS3+JS小实例:创意罗盘时钟

实例:创意罗盘时钟 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=…...

设计数据库之内部模式:SQL基本操作

Chapter4&#xff1a;设计数据库之内部模式&#xff1a;SQL基本操作 笔记来源&#xff1a; 1.《漫画数据库》—科学出版社 2.SQL | DDL, DQL, DML, DCL and TCL Commands 设计数据库的步骤&#xff1a; 概念模式 概念模式(conceptual schema)是指将现实世界模型化的阶段进而&…...

Git浅谈配置文件和免密登录

一、文章内容 简述git三种配置ssh免密登录以及遇见的问题git可忽略文件git remote 相关操作 二、Git三种配置 项目配置文件(局部)&#xff1a;项目路径/.git/config 文件 git config --local user.name name git config --local user.email 123qq.cc全局配置文(所有用户): …...

【好玩的经典游戏】Docker环境下部署RPG网页小游戏

【好玩的经典游戏】Docker环境下部署RPG网页小游戏 一、react-tetris小游戏介绍1.1 react-tetris小游戏简介1.2 项目预览二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 安装Docker环境3.2 检查Docker服务状态3.3 检查Docker版本3.4 检查docker compose…...

前端逻辑错误或UI崩溃解决问题

全屏错误覆盖层或UI崩溃 VueReact&#xff08;错误边界&#xff09; Vue Vue的全屏错误覆盖层解决&#xff0c;其实只需要配置Error就好&#xff0c;在开发服务器的client.overlay中设置关闭全屏覆盖层 module.exports {devServer: {client: {overlay: {warnings: false,error…...

python爬取QQ音乐评论信息

python爬取QQ音乐评论信息 python爬取QQ音乐评论信息1.随便选个音乐python爬取QQ音乐评论信息 1.随便选个音乐 https://y.qq.com/n/yqq/song/0039MnYb0qxYhV.html 当前的后台调试页面显示如下: 找到评论的数据接口: https://c.y.qq.com/base/fcgi-bin/fcg_global_comme…...

Unity构建详解(1)——SBP介绍

【前言】 Unity的资源工作流程分为导入、创建、构建、分发、加载。我们说的是其中的构建步骤。 构建是指将项目工程中的资源文件和代码整合程可执行文件的过程&#xff0c;构建的结果是生成可执行文件&#xff0c;在win平台上是exe&#xff0c;在Android平台上是apk&#xff…...

贪心算法(算法竞赛、蓝桥杯)--奶牛晒衣服

1、B站视频链接&#xff1a;A28 贪心算法 P1843 奶牛晒衣服_哔哩哔哩_bilibili 题目链接&#xff1a;奶牛晒衣服 - 洛谷 #include <bits/stdc.h> using namespace std; priority_queue<int> q;//用大根堆维护湿度的最大值 int n,a,b; int tim,maxn;int main(){s…...

Redis列表:高效消息通信与实时数据处理的利器

Redis是一个强大的开源内存数据库&#xff0c;被广泛应用于缓存、会话存储、队列等各种场景中。在Redis中&#xff0c;列表&#xff08;List&#xff09;是一种非常重要的数据结构&#xff0c;它提供了存储、获取、操作有序元素集合的功能。本文将深入探讨Redis列表的特性、使用…...

Redis中的缓存雪崩

缓存雪崩 &#x1f914;现象分析 缓存雪崩是指在同一时段大量的缓存key同时失效或者缓存服务(Redis等)宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 &#x1f44a; 解决方案 利用Redis集群提高服务的可用性&#xff0c;避免缓存服务宕机给缓存业务添…...

使用远程工具连接Mysql

&#xff08;若想要远程连接Mysql需要下面解决四个问题&#xff09; 1、目标地址 直接查询 2、端口号 3306 3、防火墙关闭 [rootlocalhost date]# systemctl stop firewalld.service 4、授权mysql数据库root用户权限&#xff08;因为mysql开始不允许其他IP访问&#xff0…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...