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

【C++杂货铺】详解类和对象 [上]

                                        博主:代码菌@-CSDN博客

                                        专栏:C++杂货铺_代码菌@的博客-CSDN博客


目录

🌈前言🌈

📁 面向对象语言的特性

📁 类

 📂 概念

 📂 定义

📁 访问限定符

 📂分类

 📂 封装

📁 类的作用域

📁 类的实例化

📁 类的模型

📂 类的存储

📁 面试题

📁this指针(灰常重要)

 📂 this指针的引入

 📂 this指针的特性

 📂面试题

📁 总结


🌈前言🌈

        欢迎收看本期【C++杂货铺】,这期内容,我们将围绕C++中类和对象部分内容进行讲解,包括了 封装,类的概念,如何定义类和类的大小等内容,最后我们给出工作面试出的一道题目进行讲解。

        如果你想学习C++,或者刚学完C语言衔接C++,那么这篇文章将会非常有效的帮助你理解。

📁 面向对象语言的特性

        面向对象语言有三大特性:封装,继承,多态。在类和对象中,我们重点讲解一下,什么是封装。

        例如,我们使用电脑,用户只需要知道如何与鼠标,键盘等进行交互,而不需要知道机器内部CPU,内存等是如何工作的,厂商都将其隐藏起来,封装在机箱中,这就是封装的过程。而这个机箱就是 类。

📁 类

 📂 概念

        不知道你是否学习过C语言中的结构体struct,来存储不同类型的数据。类就是结构体的进阶版,类 中不仅可以定义变量(成员变量),还可以定义 函数(成员函数)。

 📂 定义

class className
{// 类体:由成员函数和成员变量组成 ...
};struct Name
{// 类体:由成员函数和成员变量组成...
}

        需要注意的是类,不仅可以是class,也可以是struct。class定义时{}后面有 ; ,这点需要注意。

        class为定义类的关键字,ClassName为类的名字,{}内为类的主体。

        类体中的内容称为类的成员:类中的变量称为类的属性或者成员变量;类中的函数称为类的方法或成员函数

        类的两种定义方式:

        1. 声明和定义都在类体中,需要注意的是:成员函数如果在类中定义,编译器可能会将其当做是内联函数处理。(如果不懂内联函数,可以参考下面这篇文章)

【C++杂货铺】三分钟彻底搞懂函数重载-CSDN博客

        下图中,public 和 private是限定操作符。

        2. 类的声明放在 .h 文件中, 成员函数定义在 .cpp文件中。

        一般情况是,在学习竞赛中使用第一种情况;工作过程,采用第二种。

        此外,还有一个约定俗成,就是成员变量一般以 _开头,也是为了方便区分。

📁 访问限定符

        什么是访问限定符呢,就是一种限制。例如,我们的电脑,对于一个小白,那就限制他只能使用鼠标键盘等操作,不允许触碰机器内部的元器件。鼠标键盘就是共有的,机器元器件就是私有的。

 📂分类

【 访问限定符说明 】:

1. public 修饰的成员在类外可以直接被访问。
2. protected private 修饰的成员在类外不能直接被访问 ( 此处 protected private 是类似的 )。
3. 访问权限 作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class 的默认访问权限为 private struct public( 因为 struct 要兼容 C)。
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

        

        C++需要兼容C语言,所以C语言中的struct可以当成结构体来使用。另外C++中struct还可以用来定义类。和class一样,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。

(注意:在继承和模板参数列表位置也有区别,后续给大家介绍)

 📂 封装

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

封装具有一下特性:

        1. C++中数据和方法都在类中

        2. 通过C++访问限定符对成员进行限制,可以访问在公有作用域下,不可以访问在私有作用域下。

        封装的本质是一种管理,让用户更加方便的使用类。

📁 类的作用域

        类定义了一个新的作用域,类的所有成员都在这个类中。在类体外定义成员时,需要使用 :: 来标明作用域操作符指明成员属于哪个类域。

class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int  _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout << _name << " "<< _gender << " " << _age << endl;
}

📁 类的实例化

       用类 来创建对象的过程,叫做类的实例化。

1. 类是对对象进行描述的,是一个模型,限定了类有哪些成员,定义一个类并没有分配具体实际的内存空间来存储。

2. 类 可以实例化出多个对象,实例化的对象 占用实际的物理空间,存储成员变量。

📁 类的模型

        类中既有成员变量,又有成员函数,那么如何计算类的大小呢?

📂 类的存储

● 对象中包含类的各个成员

●  代码只保存一份,在对象中保存存放代码的地址

●  只保存成员变量,成员函数存放在公共的代码段

        目前,是采用第三种方法。也就是说,成员变量存在对象中,而成员函数存在代码区。因为大家想想,如果每个成员函数都存储一份相同的成员函数,会造成很大的空间浪费。

        求类的对象大小,就是看里面的成员变量。

// 类中既有成员变量,又有成员函数
class A1 {
public:void f1(){}
private:int _a;
};
// 类中仅有成员函数
class A2 {
public:void f2() {}
};
// 类中什么都没有---空类
class A3
{};
sizeof(A1) : ___4_ __    sizeof(A2) : ___1_ __     sizeof(A3) : ___1_ __
        这也说明,如果没有成员变量,类的大小为1Byte。
结论:一个类的大小,实际就是该类中 成员变量 之和,当然要注意内存对齐
注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

📁 面试题

1. 结构体怎么对齐? 为什么要进行内存对齐?
        (1). 第一个成员在与结构体偏移量为 0 的地址处。
        (2). 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
        注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
        VS中默认的对齐数为8
        (3). 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数    倍。
        (4). 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
2. 如何让结构体按照指定的对齐参数进行对齐?能否按照3、4、5即任意字节对齐?
 #pragma pack( ~ )  这个预处理指令,可以改变编译器的默认对齐数。

📁this指针(灰常重要)

 📂 this指针的引入

        如果我们实例化两个相同类的对象A,B。同时调用成员函数初始化和打印这两个对象,如下。

class Date
{
private:int _year;int _month;int _day
public:void Init(int year,int month,int day){_yeaar = year;_month = month;_day = day;}void Print(){cout<<_year<<'/'<<_month<<'/'<<_day<<endl;}
}int main()
{Date A;A.Init(1,1,1);A.Print();Date B;B.Init(2,2,2);B.Print();
}

        编译器如何识别A和B呢?通过类的模型,我们知道,A和B的所调用的函数都是同一个,都是执行相同的指令,那编译器怎么识别year,month,day是A还是B的成员变量了。

        你会发现,谁调用了,就打印,赋值给谁的成员变量。

        这就引入了this指针的概念,隐含的this指针。所有的成员函数都隐藏一个形参,调用的地方,编译器也会处理。

 void Print(Date* const this)
{cout<<_year<<'/'<<_month<<'/'<<_day<<endl;
}A.Print(&A);

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

 📂 this指针的特性

        1. this指针的类型 类型 * const 。即在成员函数中,this1指针不能被修改指向。

        2. 在形参和实参的位置不能显示写。即你不能写this,这是编译器做的事,你做了,编译器会报错。

        3. this指针只能在成员函数中内部使用。

        4. this指针的本质是 成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this这个形参,所以对象不存储this指针

        5. this指针是成员函数第一个隐含的指针形参,一般情况下由编译器通过ecx寄存器自动传递,不需要用户传递。

 📂面试题

this指针存在在哪里?B

A. 堆                B. 栈        C. 静态区        D. 常量区          E. 对象里面        

解析:

        首先排除E,因为对象实例化后,只存储成员变量,这是在类的模型中讲解的。

        其次,排除常量区,cosnt修饰的常变量本质上还是变量。

        然后,排除静态区,静态区只存储 static静态变量和全局变量。

        最后,排除堆,堆是程序员自己开辟管理的空间。

this指针可以为空吗:可以,只要不在成员函数中解引用。

        我么创建一个类的空指针,空指针作为实参传递给形参。

        ( mov的意思就是数据赋值,lea的意思就是取地址。)

        

        下面为案例,成员函数不存储在对象中,所以A->Print不是解引用,编译器会识别成Date::Print即通过A的类找到Print这个成员函数。其他成员函数也是同理。

① 在成员函数不解引用this指针。

class Date
{
private:int _year;int _month;int _day
public:void Init(int year,int month,int day){_yeaar = year;_month = month;_day = day;}void Print(){cout<<_year<<'/'<<_month<<'/'<<_day<<endl;}
}
int main()
{Date* A = nullptr;
A->Print();
}

        上面代码,会将A的值传递给this指针,但在Print中并没有解引用空指针,所以程序正常运行。

② 如果this指针为空,在成员函数解引用this指针。会发生运行错误。

class Date
{
private:int _year;int _month;int _day
public:void Init(int year,int month,int day){_yeaar = year;_month = month;_day = day;}void Print(){cout<<_year<<'/'<<_month<<'/'<<_day<<endl;}
}int main()
{Date* A = nullptr;
A->Init();
}

        上面代码,会将A的值传递给this指针,但在Init中解引用空指针,所以程序运行错误。

        总结一下,可以定义了一个类的指针为空指针,通过空指针,可以找到类的成员函数,此时,并不是空指针的解引用,此外,空指针将赋值给this指针。

        this指针可以为空,但在成员函数中解引用this指针会运行错误。

📁 总结

        总结,类就类似于struct结构体,不过可以再内部定义成员函数。

        通过学习类,了解什么是封装,即通过类将对象的属性和方法结合在一起,通过访问限定符有选择的接口提供给外部用户使用。封装的本质就是一种管控。

        当然这只是类的初窥门槛,之后的文章将逐渐揭开类的神秘面纱。

        如果这篇文章对你有所收获,欢迎点赞,评论,收藏。Thanks♪(・ω・)ノ

相关文章:

【C++杂货铺】详解类和对象 [上]

博主&#xff1a;代码菌-CSDN博客 专栏&#xff1a;C杂货铺_代码菌的博客-CSDN博客 目录 &#x1f308;前言&#x1f308; &#x1f4c1; 面向对象语言的特性 &#x1f4c1; 类 &#x1f4c2; 概念 &#x1f4c2; 定义 &#x1f4c1; 访问限定符 &#x1f4c2;分类 &#x…...

Linux 驱动开发基础知识—— 驱动设计的思想(六)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…...

Mybatis-Plus入门

Mybatis-Plus入门 MyBatis-Plus 官网&#xff1a;https://mp.baomidou.com/ 1、简介 MyBatis-Plus (简称 MP) 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、 提高效率而生。 https://github.com/baomidou/mybatis-p…...

MODNet 剪枝再思考: 优化计算量的实验历程分享

目录 1 写在前面 2 模型分析 3 遇到问题 4 探索实验一 4.1 第一部分 4.2 第二部分 Error 1 Error 2 4.3 实验结果 ①参数量与计算量 ②模型大小 ③推理时延 5 探索实验二 5.1 LR Branch 5.2 HR Branch 5.2.1 初步分析 5.2.2 第一部分 enc2x 5.2.3 第二部分 en…...

Flink多流转换(1)—— 分流合流

目录 分流 代码示例 使用侧输出流 合流 联合&#xff08;Union&#xff09; 连接&#xff08;Connect&#xff09; 简单划分的话&#xff0c;多流转换可以分为“分流”和“合流”两大类 目前分流的操作一般是通过侧输出流&#xff08;side output&#xff09;来实现&…...

CSS高级技巧导读

1&#xff0c;精灵图 1.1 为什么需要精灵图&#xff1f; 目的&#xff1a;为了有效地减少服务器接收和发送请求的次数&#xff0c;提高页面的加载速度 核心原理&#xff1a;将网页中的一些小背景图像整合到一张大图中&#xff0c;这样服务器只需要一次请求就可以了 1.2 精灵…...

Redis数据类型-string

Redis-string类型 Redis中的数据类型全局命令get&setredis中变量设置的过期时间是如何检测的 keysexistsdelexpirettlpexpirepttltype string数据类型的底层的数据结构操作string类型的常用命令get&setmset&mgetsetnxsetexpsetexincr&decrincrby&decrbyinc…...

【HDFS】一天一个RPC系列--updatePipeline

updatePipeline这个RPC一般都会配合updateBlockForPipeline RPC一起使用。 先updateBlockForPipeline、然后再updatePipeline。 建议先阅读【HDFS】一天一个RPC系列–updateBlockForPipeline 本文目标是弄清楚以下问题: 弄清updatePipeline这个RPC的作用。弄清updatePipeli…...

CentOS 7 上使用 wget 安装 Nginx 并设置开机自启

在 CentOS 7 上使用 wget 安装 Nginx 并设置开机自启&#xff0c;你可以按照以下步骤进行操作&#xff1a; 首先&#xff0c;确保你已经以 root 用户或者具有 sudo 权限的用户身份登录到 CentOS 7。 安装 Nginx 所需的依赖包。在终端中运行以下命令&#xff1a; sudo yum inst…...

Android源码设计模式解析与实战第2版笔记(一)

第一章 走向灵活软件之路 — 面向对象的六大原则 优化代码的第一步 — 单一职责原则 单一职责原则的英文名称是Single Responsibility Principle&#xff0c;缩写是SRP。 SRP&#xff1a;就一个类而言&#xff0c;应该仅有一个引起它变化的原因。 一个类中应该是一组相关性很…...

HTML+JavaScript-06

节点操作 目前对于节点操作还是有些困惑&#xff0c;只是了解简单的案例 具体操作可以看菜鸟教程&#xff1a;https://www.runoob.com/js/js-htmldom-elements.html 案例-1 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8…...

单元测试——题目十二

目录 题目要求: 定义类 测试类 题目要求: 根据下列流程图编写程序实现相应处理,执行j=10*x-y返回文字“j1=:”和计算值,执行j=(x-y)*(10⁵%7)返回文字“j2=:”和计算值,执行j=y*log(x+10)返回文字“j3=:”和计算值。 编写程序代码,使用JUnit框架编写测试类对编写的…...

详解:大数据信用报告信用等级怎么看?

在大数据技术的加持之下&#xff0c;金融风控也逐渐运用大数据技术了&#xff0c;也就是我们说的大数据或者大数据信用&#xff0c;在大数据信用报告中对个人的综合信用风险有着等级划分&#xff0c;那大数据信用报告信用等级怎么看呢?本文为你详细介绍一下&#xff0c;感兴趣…...

rsync命令常用参数详解

1、语法 Usage: rsync [OPTION]… SRC [SRC]… DEST or rsync [OPTION]… SRC [SRC]… [USER]HOST:DEST or rsync [OPTION]… SRC [SRC]… [USER]HOST::DEST or rsync [OPTION]… SRC [SRC]… rsync://[USER]HOST[:PORT]/DEST or rsync [OPTION]… [USER]HOST:SRC [DEST] or r…...

基于SpringBoot实现策略模式提供系统接口扩展能力

相信我们对策略模式都有耳闻&#xff0c;但是可能不知道它在项目中具体能有什么作用&#xff0c;我们需要在什么场景下才能去尽可能得去使用策略模式。 这里我简单的列出一个我之前在公司做的一个需求&#xff1a;跟第三方oa系统对接接口&#xff0c;对方需要回调我们当前系统…...

v43-47.problems

1.for循环 一般地&#xff0c;三步走&#xff1a; for&#xff08;初始化&#xff1b;表达式判断&#xff1b;递增/递减&#xff09; &#xff5b; ....... &#xff5d; 但是&#xff0c;如果说声明了全局变量&#xff0c;那么第一步初始化阶段可以省略但是要写分号‘ ; ’…...

华为HCIP Datacom H12-831 卷14

多选题 1、以下哪些Community属性可以保证BGP路由条目的传播范围只在AS内? A No_Export B No_Export_Subconfed C Interne D No_Advertise 正确答案 A,B 解析:Internet:缺省情况下,所有的路由都属于internet团体。具有此属性的路由可以被通告给所有的BGP对等体。n…...

《vtk9 book》 官方web版 第3章 - 计算机图形基础 (1 / 6)

计算机图形是数据可视化的基础。从实际角度来看&#xff0c;可视化是将数据转换为一组图形基元的过程。然后使用计算机图形的方法将这些基元转换为图片或动画。本章讨论了基本的计算机图形原理。我们首先描述了光线和物体如何相互作用形成我们所看到的景象。接下来&#xff0c;…...

负载均衡是什么,负载均衡有什么作用

一、什么是负载均衡 负载均衡是一种在计算机网络和系统架构中使用的技术&#xff0c;用于均衡分发工作负载到多个资源&#xff0c;比如&#xff1a;服务器、计算节点或存储设备上&#xff0c;以提高系统的性能、可伸缩性。 在传统的单个服务器架构中&#xff0c;当请求量增加…...

Leetcode 3020. Find the Maximum Number of Elements in Subset

Leetcode 3020. Find the Maximum Number of Elements in Subset 1. 解题思路2. 代码实现 题目链接&#xff1a;3020. Find the Maximum Number of Elements in Subset 1. 解题思路 这一题我做的是比较水的&#xff0c;首先就是统计下array当中各个元素出现的频次&#xff0…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢&#xff0c;连接红外测温传感器&#xff0c;可实时精准捕捉宠物体温变化&#xff0c;以便及时发现健康异常&#xff1b;水位检测传感器时刻监测饮用水余量&#xff0c;防止宠物…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...