当前位置: 首页 > 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…...

Qwen3-ASR-1.7B部署案例:高校科研组构建本地化学术讲座语音知识库

Qwen3-ASR-1.7B部署案例&#xff1a;高校科研组构建本地化学术讲座语音知识库 1. 项目背景与价值 高校科研团队经常举办各类学术讲座和研讨会&#xff0c;这些宝贵的学术内容通常以音频形式记录。传统的人工转录方式耗时耗力&#xff0c;且对于专业术语密集的学术内容&#x…...

自指宇宙学:存在如何通过自我描述而实在化(SRC-2024)

自指宇宙学&#xff1a;存在如何通过自我描述而实在化 Self-Referential Cosmology: How Existence Becomes Real Through Self-Description方见华 世毫九实验室 摘要&#xff1a;本文提出“自指宇宙学”(SRC)&#xff0c;论证宇宙的实在性源于其自我描述能力。我们发现&#x…...

【开题答辩全过程】以 校园创新创业管理系统设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…...

如何永久保存微信聊天记录:3步实现数据自主管理的完整指南

如何永久保存微信聊天记录&#xff1a;3步实现数据自主管理的完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

构建自主海上防御系统:Mirai Robotics融资420万美元

Mirai Robotics已筹集420万美元的Pre-Seed轮资金&#xff0c;旨在构建自主和智能的海上系统。本轮融资由Primo Ventures、Techshop和40Jemz Ventures领投&#xff0c;并有来自意大利和国际的天使投资人参与。 海洋是地球上最关键的基础设施之一。全球超过80%的贸易通过海路运输…...

LFM2.5-1.2B-Thinking-GGUF入门指南:Web UI界面功能与Thinking后处理解读

LFM2.5-1.2B-Thinking-GGUF入门指南&#xff1a;Web UI界面功能与Thinking后处理解读 1. 模型与平台简介 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型&#xff0c;专为低资源环境优化设计。该模型采用GGUF格式存储&#xff0c;配合llama.cpp运行时&#x…...

Nunchaku-flux-1-dev在Typora文档中的自动插图生成

Nunchaku-flux-1-dev在Typora文档中的自动插图生成 1. 引言 写技术文档最头疼的是什么&#xff1f;对我来说&#xff0c;一定是配图。每次写到关键的技术概念或者流程说明&#xff0c;都得停下来去找合适的示意图&#xff0c;或者打开绘图工具手动制作。不仅打断思路&#xf…...

FPGA仿真提速秘籍:手把手教你配置VSCode,一键运行iverilog编译+GTKWave看波形

FPGA仿真效率革命&#xff1a;VSCodeiverilogGTKWave全自动化工作流实战 在数字电路设计领域&#xff0c;仿真验证环节往往占据整个开发周期60%以上的时间。传统基于命令行的仿真流程需要工程师反复输入冗长指令&#xff0c;手动切换多个工具界面&#xff0c;这种低效的工作模…...

从报错到解决:Pycharm中Tensorflow2.x与1.x代码兼容性问题全解析

从报错到解决&#xff1a;Pycharm中Tensorflow2.x与1.x代码兼容性问题全解析 在深度学习领域&#xff0c;TensorFlow作为最受欢迎的框架之一&#xff0c;其版本迭代带来的变化常常让开发者感到头疼。特别是从TensorFlow 1.x升级到2.x版本后&#xff0c;许多核心API发生了重大改…...

Qwen3-VL-8B医疗效果实测:CT报告截图→关键指标提取→通俗化解读

Qwen3-VL-8B医疗效果实测&#xff1a;CT报告截图→关键指标提取→通俗化解读 1. 引言&#xff1a;当AI医生遇上CT报告 想象一下这个场景&#xff1a;你拿到一份CT检查报告&#xff0c;上面密密麻麻写满了医学术语和数字。你盯着“肺窗示双肺纹理增多、增粗&#xff0c;可见多…...