【C++】类和对象(初阶认识)#上篇#

news2024/11/25 18:45:25

目录

 对面向过程和面向对象的初步认识

类的引入

封装 和 类的访问限定符

所以祖师爷在类中还引入了访问权限

用类定义变量

类的理解和对象的实例化

 

sizeof 计算类对象的大小

类对象的成员函数在公共代码区

this 指针


  1.  对面向过程和面向对象的初步认识

什么,是面向过程?

那生活中的洗衣服来做栗子:比如手搓洗衣服这件事,这个过程中,包含了

 拿衣服 → 拿洗衣粉 → 放水浸泡 → 用洗衣粉手搓 → 涤第二遍 → 晒衣服

面向过程在这里是更关注洗衣服每个步骤的过程,关注的是过程

但是这样的话就要我们的使用者就得比较有要求,你得会洗衣服,要有耐心等

而对应到我们编程的面向过程,关注的也是过程,这样可能很多方面关于对象(使用者等)的考虑可能就会欠佳,并且对于对象(使用者等)可能就有更高的要求

而面向对象呢?

面向对象同样也用洗衣服为引例:这里更像是用洗衣机洗衣服

 我们拿要衣服 → 放进便利我们、面向我们的洗衣机 → 晒衣服完事

我们的面向对象在这里更关注的是我们,让我们更方便、系统地洗衣

这样的话对于对象(我们使用者)来说,是很有方便,系统有效的

而对应到我们编程的面向对象,关注的是对象。更面向于使用者,这样可能会让过程更麻烦与否,但是这是面向于对象,服务于对象才是我们的目标  在人的世界中可以说面向对象是优于面向过程的

  1. 类的引入

在C语言中,相比其他语言最大的特点之一,是太自由了,我们的数据(变量等)和 方法(函数等)是分离的。比如用C语言实现的一个栈

栈栈

可以看到,不管是 StackPush 、StackPop 还是其他函数,函数是和结构体分离的,而数据一般捆绑在我们的结构体中,其结果是函数和我们的数据是分离的。这样的函数与数据分离的结果是什么?我们可以拿到任意局部的数据去进行修改,或者不修改;只要方法正确,我们可以没有限制操控地、细致地操控很多东西……这就是自由,没有过多的限制同样决定了C语言是更关注过程的一门语言,我们可以用它实现很多非常巧妙的函数(那些很优很优的算法很多都是C语言实现的)

但是世界是发展的,更多事物是服务于人,计算机也是;所以只有面向过程是不够的,我们也需要一门更加面向对象的语言,去服务于我们,或其他事物,也能让我们更加方便与规范

C是满足不了,但是祖师爷可以

                                  —— 所以 ,诞生了

类的格式:

class Stack

{

//public:

Init();          //函数这里没展开实现

Push();

Pop();

Destroy();

//private:

int *_p;

int _top;

int _capacity;

};

理解李姐:

C语言中,因为结构体中只能是捆绑数据,所以定义了一个结构体变量更相当于创建了一个集成的数据,形成一个大的数据域,它更面向于我们的函数,可以说是更面向于过程;

但是现在,我们的类是将数据和方法都捆绑到一起,函数也可以和数据捆绑起来,这样我们用类定义的一个变量更相当于一个对象,类中有的函数可以通过这个对象去调用,相当于对象在行使它所拥有的权力。假设我们用类来实现商家这一类群体,类中的数据可以是商家的个人数据,可以用我们熟悉的数据结构来进行存储商家信息作为我们的数据;类中的函数就是商家可以行使的权力,比如修改自己的信息(修改自己对应的数据部分),货品上架等,这些是类中的函数完成

—— 哦哦

定义变量且不看,先来了解面向对象的第一个特点:封装

封装 和 类的访问限定符

要了解封装,害(hai弟叁牲)得先从自由人C语言讲起

C语言的结构体中数据和方法是分离的,肥肠自由

—— 但是,自由性很高也往往不是一件好事

面向过程的自由人可以完成很多细致的操作,很多高级的函数;函数很优固然是好,但是对象是我们,我们是使用者,越细致的操控意味着使用者要注意的地方有很多,对于对象的要求也就越高:

栗子:

可能你有 必须严谨包装、在36~46度生存的化学限量版洗衣粉,效果虽然很好但是使用者一旦操作不当就会出错;

或者说刚刚的栈,栈本身是后来入栈的元素在栈顶上,但是自由度高有的对象就有可乘之机,挪栈中全部元素空出栈底,把后来的元素放到栈底,本来你应该在栈顶的呀;如果说这样在一些情况下可以有利,那没事;但是如果是一个不能插队的排队系统呢,有人这样干呢!!后面的元素会想刀人的,关键在代码实现层面没有有效的办法去管控它(可以但是可能会异常繁琐)

再举一个刚刚的例子(栗子),刚刚实现的栈中,栈的数据部分捆绑在一个结构体中,结构体中的top有两种初始化方式:

top = 0; 表示 top 指向入栈位置

top = -1; 每次入栈时, top要先自增,再进行入栈元素的赋值:相当于top指向的是入栈位置的前一个位置

现在在看到我们的入栈函数,其核心代码也就只有一行两行;但是有的人看到了说直接在要使用的时候直接 arr[++top] = 入栈元素;   但是一运行发现出错了,最后调试发现 top 初始化为 0,就指向入栈位置,应该这样写:arr[top++] = 入栈元素;     这也是一种不规范的行为

这里我们可以看到:如果数据和方法分离(比如刚刚的不调用函数直接入栈),我们自己要控制的也越多,有些人也不会讲规范,很容易出错。对于个人是很讲究代码规范的,看到刚刚的直接入栈那种不规范操作更是嫉恶如仇

我们看到,C语言这样数据和分离的方法在面向过程中是非常牛的,很多很多问题最优解也是用C语言写的;

但是数据和分离的这种方法在对于对象来说,很多时候对于对象的要求就要求会很高,有些人会很不规范,对于不规范操作我是嫉恶如仇,当然祖师爷也是

祖师爷想,既然C语言那么多人会代码不规范,提高每个人的素质比较困难,但是可以改变语法

—— 《既然改变不了世界,那就改变自己篇》

所以祖师爷在类中还引入了访问权限

开始了开始了

 

祖师爷设计了三种访问权限:

public:公有的。类中成员的属性为 public 表示该成员可以在类的外部直接被访问

protected:被保护的。类中成员的属性为 protected 不能在类的外部直接访问该成员

private:私有的。类中成员的属性为 private ,表示该成员不能在类的外部直接被访问

用法简单,如下:

属性为 public 的成员可以在类外面直接访问,被 private 修饰的成员不能被直接访问(这里错误展示就不写啦,有点小锉锉,不是理由)

一般我们把要给对象用的成员函数属性设置为 public ,而不想让对象改动的数据设置为私有 private ,这样对象在类外就只能调用你规定好的函数,让使用者更加规范地、方便地、系统地去访问数据等操作,将不规范扼杀在了摇篮里

这样设计带来的规范和方便时给人的,所以这里也体现了 面向对象(关注的是对象)

其实了解了这个,大概想想就可以猜到封装的意思了

类的封装:将数据和方法有机结合,不提供对象的属性和细节,只提供对象成员函数的接口,以此来进行和对象的交互

(不提供 对象 成员函数的实现细节 和 各数据 ,只给你调用成员函数来对对象的数据等进行修改)

这样很大程度上提高了我们的代码的规范性,用起来好方便,呜呜祖师爷真好,祖师爷以德报怨,爱死祖师爷了

现在类的基本格式和定义搞清楚了,来看看怎么用类来定义变量

用类定义变量

和C语言的结构体不同,结构体在定义变量时要加上 struct,不能直接是结构体名字来定义变量

而在类中,是直接使用:类名 + 变量名   来定义变量 (etc.     Stack S; )

(大概是祖师爷也觉得每次定义要加struct太麻烦了,直接改掉了)

etc.   //与上面格式代码对应

Stack S;

对的,just这样方便

但是有人发现在C++中使用 struct 定义的类型也可以直接用 类型 + 变量名  来定义变量

那是因为在C++中,struct 定义的类型也被升级成了类;也就是说,C++使用 struct 和 class 定义的都是类,定义的不是结构体哦

那有人说,struct 定义出来的类和 class 定义出来的类没有任何差异吗?有,但不多

就一个地方:

struct 定义出来的类,其成员的属性默认为:public

class  定义出来的类,其成员的属性默认为:private

就一个公私有的问题啦,不过日常我们的数据不愿意被外部直接访问到,如果忘记手动修饰成员的属性,class 会更安全健壮点

类的理解和对象的实例化

思考,只是定义好了一个类,它里面的数据有没有开空间?

早在C语言的结构体中,刚定义好的结构体类型只是声明,其中的成员变量没有分配空间,只是声明,声明这个结构体类型里有这个成员;而到了真正定义了一个结构体变量时,才根据刚刚的声明去开辟空间,按成员声明分配空间

C++中刚定义好的类也是声明,其中的变量是声明该类中有该成员,并没有真正开辟空间

注意,这里的成员变量 _pa  _top  _capacity  还没有开辟空间,只是声明,声明此类中有该成员变量

那在什么时候初始化呢?

在对象被定义的时候,也就是在对象实例化的时候,才真正在本函数栈帧中(或其他存储空间中)开辟大小为 类的大小 的空间,按成员变量的声明依次分配内存空间给它的成员变量

形象地加深理解:

我们可以看到,其实头文件中的类更相当于一张图纸,一张蓝图;而用这个类创建了对象,才是用这个图纸将物体创造出来,因为创建好对象才真正开辟了空间,一定要理解清晰,每次写之前就应该想到

用类来创建对象的时候才分配空间,所以给这个过程一个形象的名字,叫做对象的实例化

继续添加内容

sizeof对象的问题,图纸和公共代码区

 

sizeof 计算类对象的大小

要讲到计算一个类对象的大小,得先了解:

类对象的成员函数在公共代码区

和结构体计算大小不同,类中除了有数据,比结构体还多了成员函数这一东西

那计算大小时要不要算进成员函数的大小去呢?

那得看对象的栈帧里面是不是有成员函数的栈帧

先构想:如果成员函数的栈帧在对象里面,那创建的每一个对象内部都有该函数,用的时候调用它。这样固然可以,但是重复的那段函数代码是不是很冗余啊?这样设计是不是很挫啊 —— 祖师爷当然不会那样干

这就好比一个对象相当于一个房子,然后成员函数相当于日常大家都要用的足球场,现在如果在对象里面都塞一个函数的空间,相当于每个房子里都装修一个足球场

祖师爷怎么做呢?祖师爷把成员函数的栈帧空间放到了公共代码区,不在单个对象里面,而是每个对象(同一类)要使用该函数时,都去公共代码区调用该函数,相当于只要定义一个函数栈帧 大家一起用。这就相当于把足球场 修在了小区里面,每个房子的人可以使用同一个

所以成员函数的函数栈帧是不在对象里面的,而是在公共的代码区,所以计算大小时,也不用计算每个对象里面成员函数的大小

所以剩下的就只是数据了,这下和C语言结构体计算大小就一样了

  1. this 指针

类中的私密数据不是不可以在外部访问到嘛,调用成员函数才能访问私密数据,那编译器是怎么实现的呢?它的底层又是什么呢?

先来看函数对象调用成员函数的一些特点

我们看到当类的对象调用其成员函数时,格式是:对象.成员函数(传参);

调用的汇编代码如下:

  

其实对象调用成员函数的底层还会有一个 this 指针,这是属于每一个成员函数的浪漫(每一个成员函数都有这个 this 指针)

this 指针 是一个隐含的参数,比如在调用 S1 中的 Push() 函数时,this指针 是一个隐含的参数

在调用 S1.Push() 时,编译器会 取 S1的地址 给 this指针,等到了成员函数内部,就可以用这个 this指针 可以用来访问 S1 中的数据(权限够),这就是调用成员函数修改数据的实现

清晰具体的过程吧:


S1.Push(1);    

底层汇编是 lea      rcx, [S1]       意思是取S1的地址给寄存器 rcx

等到了(公共代码区的)成员函数, 寄存器 rcx 将寄存的 S1的地址 给到 this指针,要使用S1该对象里的数据时,是通过this指针来实现的

用刚刚的栈举栗子:

我们一般在成员函数内部直接写:_capacity = Init_SZ;  

这样可以访问到 S1中的 _capacity,是因为底层是这样的:this->_capacity = Init_SZ;

是通过this指针来访问到 S1 中的数据;这里又一次体现出 C嘎嘎更多是让编译器帮我们完成了操作,而不是实质性地改变C语言

 

是成员函数就有 this 指针(这是属于每一个成员函数的浪漫)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/499240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分片集群-搭建

分片集群 高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。 为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。 垂直扩展:增加更多的…

阿里云服务器地域和可用区怎么选择合适?

阿里云服务器地域和可用区怎么选择?地域是指云服务器所在物理数据中心的位置,地域选择就近选择,访客距离地域所在城市越近网络延迟越低,速度就越快;可用区是指同一个地域下,网络和电力相互独立的区域&#…

ROHM常见的电冰箱控制电路图,轻松了解冰箱工作原理

​冰箱是我们日常生活中使用频率非常高的电器,它可以将食物和饮料保存在低温下,以延长它们的保质期。冰箱的工作原理主要基于制冷循环和温度控制。 先看电路图: 1. 单门直冷式电冰箱重锤式控制电路 电路的基本组成:采用重锤式启…

win10安装pytorch全网最好用的教程[2023.5.7更新]

目录 0.关于pytorch a. 什么是 PyTorch ? b. 为何选择 PyTorch ? 1.安装pytorch 1.1确定关联性 1.2下载最新版本的pytorch 1.3.pytorch历史版本下载 1.4 避坑 1.4.1、猜测 1.4.2、验证 1.4.3、解决方案 1.5、检验 0.关于pytorch a. 什么是…

前端学习----webpack入门学习

webpack是前端项目工程化的具体解决方案 主要功能:它提供了友好的前端模块化开发支持,以及 代码压缩(将空格和注释全部消除,变成一行代码)、 处理浏览器端JavaScript的兼容性(只管写高级语法,自动向下兼容。例如ie8不支持let 语法…

【Shell】一天快速入门

1 Shell解析器 Linux提供的shell解析器有6种: /bin/sh /bin/bash /sbin/nologin /bin/csh /bin/dash /bin/tashsh是bash的软连接。 2 Shell脚本 2.1 hello.sh脚本 #!/bin/bash echo hello world!#! 告诉系统这个脚本需要什么解释器来执行; 脚本以#!…

NCNN----Monodepthv2单目深度估计 小米手机部署

题目要求:学习了解单目深度估计模型MonoDepthv2,基于NCNN推理框架部署到小米手机 MonoDepthv2 论文:Digging Into Self-Supervised Monocular Depth Estimation MonoDepthv2 源码:Monodepth2 GitHub 分析: 1&#xff0…

Illustrator如何进行任务自动化之实例演示?

文章目录 0.引言1.动作的录制2.对文件播放动作3.批处理 0.引言 因科研等多场景需要进行绘图处理,笔者对Illustrator进行了学习,本文通过《Illustrator CC2018基础与实战》及其配套素材结合网上相关资料进行学习笔记总结,本文对任务自动化进行…

Cadence技巧总结学习(DRC、Annotate)持续更新~

Cadence技巧总结学习持续更新~ 你还可以再哪里看到这篇文章:知乎 1. 画叉 对于芯片上不用的引脚信号画上号,如下: 按大写X就可以了,或是双脚引脚,在跳出的界面中,Is No Connect上✔。 2. 画线快捷键&#…

【关于C++中----智能指针】

文章目录 一、概念引入二、内存泄漏2.1 内存泄漏概念及其危害2.2 内存泄漏分类2.3 避免内存泄漏 三、智能指针的原理3.1 RAII3.2 像指针一样 四、三类智能指针4.1 auto_ptr4.2 unique_ptr4.3 shared_ptr 五、循环引用和weak_ptr 一、概念引入 在我们日常写代码过程中&#xff…

ARM学习(21)STM32 外设Can的认识与驱动编写

笔者来聊聊can的认识以及can接收数据的驱动编写 1、STM32 Can 外设的认识 Can的特性就不多说了,主要来聊聊can的一些标识符以及收发状态。can有一套收发机制,发送和接收都有硬件缓存,叫邮箱,通过下面的图可以看出,下面…

ESP32学习笔记 -- ESP32-S3 使用外部 PSRAM

ESP32-S3是乐鑫科技推出的一款专为物联网而生的SOC芯片,该芯片同时支持WIFI和BLE蓝牙功能,集成了高性能的Xtensa 32位LX7双核处理器,最高主频可达240MHz。 根据乐鑫官方资料介绍,该芯片内置512KB SRAM片上内存,并且具有45个可编程GPIO管脚和丰富的通信接口。为了更好地扩…

Flask框架之路由与蓝图的使用

路由与蓝图 路由路由概述路由的基本使用查看路由信息url_map对象命令行方式 HTTP请求方法 蓝图概述蓝图的基本使用蓝图的拆分指定蓝图的url前缀蓝图构造URL蓝图静态文件蓝图模板目录 路由 路由概述 在Flask中,路由用于将HTTP请求与特定的Python函数相匹配。通过定义…

K8s-Pod概念、创建及常用命令

文章目录 一、Pod概念1、Pod是什么?2、Pod网络共享实现方式3、Pod存储共享方式4、创建Pod整体流程 二、使用YAML文件定义Pod资源1、Pod资源清单YAML文件书写技巧1. YAML语法格式:2. 配置Linux tab缩进两个空格3. 使用kubectl explain帮助命令 2、创建Pod…

章节2:01-Java序列化和反序列化

章节2:01-Java序列化和反序列化 01-Java序列化和反序列化 基础环境 JDK解压版:包含Java运行时环境 IDEA:开发工具 Maven:jar包依赖管理 Tomcat:HTTP服务器 Burp Suite:发送HTTP请求 Kali&#xff1…

ANSYS APDL谐响应分析——悬臂梁的频响函数计算以及幅值、角度(相位)、分贝计算

问题描述 研究一根悬臂梁,材质为钢材。长度 L 2 L2 L2 米;截面为矩形,矩形的长度为 H 5 c m H 5cm H5cm,宽度为 B 2 c m B 2cm B2cm 。 建模思路: 先建立节点,然后用节点生成单元。使用n命令&…

book-riscv-rev1.pdf 翻译(自用,更新完成)第一章 操作系统接口

Job of operating system: 操作系统使得多个程序分享一台计算机,提供一系列仅靠硬件无法支持的服务。 管理与抽象低级别硬件(如:文件处理程序不需要关注使用哪种硬盘)使得多个程序分享硬件(programs that can run at…

797. 差分(C++和Python3)——2023.5.7打卡

文章目录 QuestionIdeasCode Question 输入一个长度为 n 的整数序列。 接下来输入 m 个操作,每个操作包含三个整数 l,r,c ,表示将序列中 [l,r] 之间的每个数加上 c 。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两个整数 n 和 m 。 第二…

高性能流媒体硬解码

目录 高性能流媒体硬解码前言1. What、Why and How1.1 What1.2 Why?1.3 How? 2. 离散傅里叶变换(DFT)2.1 JPEG编码2.2 哈夫曼编码(Huffman Coding) 3. 视频流媒体前置知识3.1 视频文件的构成3.2 视频的编码与封装3.3 H264编码的分层3.4 RTSP之RTP(Real-t…

【clang】安装clang编译器并将linux默认编译器改为clang

目录 省心操作法手动安装 本文是他人智慧的总结个人实践。 省心操作法 缺点: clang版本不能自己选择;我的系统是ubuntu 20,安装后是clang10.0版本 优点:省心,基本不会踩坑 手动安装 参考这篇文章ubuntu20.04 安装cl…