【逐步剖C++】-第一章-C++类和对象(上)
前言:本文主要介绍有关C++入门需掌握的基础知识,包括但不限于以下几个方面,这里是文章导图:
本文较长,内容较多,大家可以根据需求跳转到自己感兴趣的部分,希望能对读者有一些帮助
那么本文也主要以导图为思路进行分享,话不多说,让我们开始吧。
一、关于类的理解与意义
1、理解
什么是类呢?可以直接根据其表面来理解。这个“类”我们常说的给事物分类的“类”,比如,动物类,交通工具类等等。通过给不同的事物进行分类,能让我们更有条理性、更系统地认知这个世界。同样的道理,类的设计可以让我们的代码编写更具逻辑性、可维护性等等。以上就是对类的简单理解。
2、意义
那么类的设计有什么意义呢?基本的意义上述也提到了,能增强代码的可维护性等,它能将具有协同功能代码封装成一个整体,从而更好地进行管理;更多对其意义的感知还是需要通过不断的学习,和代码实践来逐步加强。
关于类和对象的更形象理解方式大家感兴趣地可以去搜搜文章和书籍,本文主要还是以学习笔记的方式来展现知识内容,这里就不再赘述。
二、类的定义方式
1、关于兼容C后的结构体
由于C++兼容C,所以在C++中结构体被升级成了类。在C中的结构体只能定义成员变量,升级成类后也可以定义成员函数。但二者仍有一些区别,下文会继续进行说明。
2、定义方式
类的定义方式如下:
class typename
{};
其中class为定义类的关键字;typename为用于定义该类的类名;花括号中为类的具体内容;最后别忘了分号。
在实际工程中定义类时,我们可以根据需求将类声明(主要是其中成员函数的声明)放在头文件中,在.cpp文件中再对类中的成员函数进行定义。
三、类的访问限定符及封装的理解
类访问限定符是C++实现封装的主要方式。通过访问限定符,可以选择性地将类中的成员展现给外界用户。和平常被我们使用的电子产品一样,都是将简单易用的功能展现给我们,而将复杂的实现细节封装起来。
1.类的访问限定符
(1)类的访问限定符一共有三种,分别是:public
、protected
、private
对以上三种访问限定符的说明如下:
- 被pubilc修饰的成员能在类外直接访问
- 被protected和private修饰的成员不能在类外直接访问,(PS:关于protected和private的区别在继承章节会提到,平常使用可认为二者类似)
- 访问限定符的作用范围是:从当前访问限定符开始到下一个访问限定符出现;若下一个访问限定符一直未出现,则右花括号为止。
- class关键字定义的类默认的访问权限为private;struct关键字定义的类的默认范围权限为public(兼容C)
(2)类访问限定符在程序生命周期中作用的阶段:编译阶段。即访问限定符只在编译阶段有用,当数据映射到内存后,没有任何访问限定符上的区别。
2、对封装的理解
封装是面向对象的三大特性之一(封装、继承、多态)。对封装的理解其实很简单,前文也有谈到,其实就是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,对外仅公开使用工具(接口)来和对象进行交互。本质上属于一种管理,让用户更方便的使用类,也让类的设计更加规范化。
四、类的作用域与实例化
1、类的作用域
类的作用域也属于“域”的一种,至此我们所认识的“域”,一共就有如下三种:
- 局部作用域
- 全局作用域
- 命名空间域
- 类作用域
在笔者的另一篇文章【逐步剖C++】-第一章-C++入门知识的命名空间部分中,提到了用域访问符::
访问命名空间,这里我们也有该符号的使用需求,请看:
在类外定义成员函数时,需使用域访问符指明成员函数属于哪个类域,请看下面代码例:
class test
{
public:void testFunc();
}void test::testFunc()
{//...
}
2、类的实例化
类的实例化,本质就是通过类创建一个对象,实例化出来的对象占实际的物理空间,存储类的成员变量。由此可见,类在没有实例化之前,系统并没有为其成员变量并开实际的空间,在这个阶段成员变量仅是声明;当进行类的实例化时,成员变量才得到整体定义。
这里有一个形象的理解方式:
类的实例化过程就像拿着建筑设计图造出房子的过程。类就好比设计图,仅对房子中的内容、布局等进行规划与设计,并没有实体的建筑存在。所以,仅有一个类的定义本质是不占空间的,只有实例化出对象后,才占物理空间而实际存储数据;同理也不能直接在类外对类中声明的成员变量进行赋值,就好比设计图中不能直接住人。
五、类对象的大小计算
这里通过三个类的例子进行对类对象的大小计算的说明:
// 类中既有成员变量,又有成员函数
class A1 {
public:
void f1(){}
private:
int _a;
};// 类中仅有成员函数
class A2 {
public:
void f2() {}
};// 类中什么都没有---空类
class A3
{};
上面三个类实例化出的对象的大小分别为4字节、1字节、1字节。
解释:
在类中,对于成员变量和成员函数的大小计算不同:
- 对于成员变量,相同类实例化出的每个对象的成员变量是不一样的,就好比同一张设计图造出来的房子都有卧室,但这两个卧室一定是不同的;计算它们的大小时,和结构体一样,采用内存对齐的方法进行计算即可。关于内存对齐,可以看看笔者这篇文章:【逐步剖C】-第十章-自定义类型之结构体、枚举、联合
- 对于成员函数,相同类实例化出的每个对象其实是一样的,成员函数就像是篮球场、健身房等场所,不用每家都建而建成公共的,这样就避免了由于重复而引起的空间浪费,那么类中的成员函数存储方式类似,其会以成员函数表的形式放在一个公共的代码段中,当类的对象需要调用成员函数时,就到这个公共代码段中找对应的函数地址来完成调用,其实际不在类中(不占空间)。
验证:
class A
{
public:void Test(){cout << "void Test()" << endl;cout << _a << endl;}
private:int _a = 0; //成员变量缺省值,后续章节会说明
};
int main()
{A a1;A a2;a1.Test();a2.Test();
}
运行后转到反汇编:
可以看到,同一个类的两个不同对象所调用的成员函数的地址相同(PS:图中红框就是代码中的Test函数,蓝框是A类的默认构造函数,后续章节会进行说明)。
那么在最开始的代码例中,类A1的大小即为其成员变量的大小;类A2和类A3的大小类似,编译器会给他们一个字节来唯一标识这个类的对象。
六、this指针
1、this指针的本质
场景引入:在上面的例子中,我们通过类A实例化了两个对象,并且这两个对象都调用了成员函数Test()
,那么编译器是如何知道是哪个对象调用的呢?这就是this指针解决的问题了。
C++编译器给每个非静态的成员函数增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),指针中的内容即为对象本身的地址,在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
即例子中两条调用语句其实可理解为:
a1.Test(&a1);
a2.Test(&a2);
需要注意的是,如上仅作为一种理解方式,实际不能这么写,因为编译器规定this指针不能在实参和形参显示传递,仅可以在成员函数内部显示使用。
如:
class A
{
public:void Test(){cout << "void Test()" << endl;cout << _a << endl; //编译器自动处理this指针//也可显示使用写为:cout << this->_a << endl;}
private:int _a = 0; //成员变量缺省值,后续章节会说明
};
2、this指针的特性
- this指针的类型其实为
const 类的类型*
,如上A类的对象的this指针类型就为A* const
,即不能改变指针所指向的对象,而可以改变对象中的具体内容(成员变量等); - 只能在成员函数中显示调用;
- this指针本质上是成员函数的形参,当对象调用成员函数时,编译器一般通过ecx寄存器自动将对象地址作为实参传递给该形参。故在类的对象中不存储this指针;
3、关于this指针的一些问题
了解了this指针的特性后,下面有一些常被提起的关于this指针的问题,请看:
- this指针可以为空吗?
可以通过下面这一段代码来认识并解决这个问题:
class A
{public:void Print(){cout << "Print()" << endl;}void PrintA(){cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();p->PrintA();return 0;
}
p是一个A类对象的指针,将其赋值为空指针后用以模仿this指针来调用A类中的成员函数。运行结果如下:
可以看到,第一个函数Print()正常调用,在调用第二个函数时系统崩溃。原因很明显:p
是一个空指针,在调用第一个成员函数时,本质上并没有访问该指针所指向位置的内存(对象的具体内容);而在调用第二个成员函数时,程序想访问并输出类的成员变量_a
,那么此时的行为就相当于解引用一个空指针而去访问其指向的内容,也就是我们常说的野指针问题,故造成了程序的崩溃。
综上,this指针一般情况下不会为空。
- this指针存储在哪里?
第二个问题其实在介绍this指针的特性时已给出了答案,this指针本质上是成员函数的形参,那么既然是形参,也就是局部变量,那就一定存储在栈区当中。
本章完。
看完觉得有觉得帮助的话不妨点赞收藏鼓励一下,有疑问或有误地方的地方还请过路的朋友们留个评论,多多指点,谢谢朋友们!🌹🌹🌹
相关文章:
【逐步剖C++】-第一章-C++类和对象(上)
前言:本文主要介绍有关C入门需掌握的基础知识,包括但不限于以下几个方面,这里是文章导图: 本文较长,内容较多,大家可以根据需求跳转到自己感兴趣的部分,希望能对读者有一些帮助 那么本文也主要…...
索尼 toio™ 应用创意开发征文|探索创新的玩乐世界——索尼 toio™
导语: 在技术的不断进步和发展中,玩具也逐渐融入了智能化的潮流。索尼 toio™作为一款前沿的智能玩具,给孩子和成人带来了全新的游戏体验。本文将介绍索尼 toio™的特点、功能和应用场景,让读者了解这个令人兴奋的创新产品。 1. 了…...
企业架构LNMP学习笔记23
1、隐藏版本号: Nginx对外提供服务,为了避免被针对某个版本的漏洞进行攻击。经常做法是隐藏掉软件的版本信息,提供一定的安全性。 server_tokens off; https和CA: 1)基于SSL CA证书的公私钥的安全性。 CA是需要生成…...
第六章 图 五、图的深度优先遍历(DFS算法)
目录 一、定义 深度优先遍历通常用于解决以下问题: 深度优先遍历算法具有以下优点: 深度优先遍历算法的一个缺点是: 二、代码 空间复杂度: 时间复杂度: 邻接矩阵存储: 邻接表存储: 三、…...
React 中的 useLayoutEffect 钩子函数
useLayoutEffect钩子函数的作用跟useEffect钩子函数的作用一样,它们的不同主要是在于: 1、useEffect钩子函数是异步的,因为此函数在执行的时候是先计算出所有的 Dom 节点的改变后再将对应的 Dom 节点渲染到屏幕上,然而在 useEffe…...
upload-labs1-21关文件上传通关手册
upload-labs文件上传漏洞靶场 目录 upload-labs文件上传漏洞靶场第一关pass-01:第二关Pass-02第三关pass-03:第四关pass-04:第五关pass-05:第六关pass-06:第七关Pass-07第八关Pass-08第九关Pass-09第十关Pass-10第十一…...
MATLAB遗传算法求解生鲜货损制冷时间窗碳排放多成本车辆路径规划问题
MATLAB遗传算法求解生鲜货损制冷时间窗碳排放多成本车辆路径规划问题实例 1、问题描述 已知配送中心和需求门店的地理位置,并且已经获得各个门店的需求量。关于送货时间的要求,门店都有规定的时间窗,对于超过规定时间窗外的配送时间会产生相应的惩罚成本。为保持生鲜农产品的…...
界面控件DevExpress .NET应用安全 Web API v23.1亮点:支持Swagger模式
DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。 DevExpress 今年第一个重要版本v23.1日前已正式发布了,该版本拥有众多新产品和数十…...
SpringMVC之CRUD------增删改查
目录 前言 配置文件 pom.xml文件 web.xml文件 spring-context.xml spring-mvc.xml spring-MyBatis.xml jdbc.properties数据库配置文件 generatorConfig.xml log4j2日志文件 后台 PageBaen.java PageTag.java 切面类 biz层 定义一个接口 再写一个实现类 …...
微信小程序开发教学系列(4)- 抖音小程序组件开发
章节四:抖音小程序组件开发 在本章中,我们将深入探讨抖音小程序的组件开发。组件是抖音小程序中的基本构建块,它们负责展示数据和与用户交互。了解组件的开发方法和使用技巧是进行抖音小程序开发的重要一步。 4.1 抖音小程序的基本组件 抖…...
RabbitMQ反序列化失败:Failed to convert message
🎈 1 参考文档 RabbitMQ消费消息坑:failed to convert serialized Message content | jiuchengi-cnblogs 🔍2 问题描述 org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert messageat org.sprin…...
CTFSHOW 年CTF
1.除夕 php的弱类型,用小数点绕过 这里后面直接加字母不行 2.初三 error_reporting(0); extract($_GET); include "flag.php"; highlight_file(__FILE__); 这里通过extract将get的参数导入为了变量 $_function($__,$___){return $__$___?$___:$__; }; …...
肖sir__设计测试用例方法之状态迁移法05_(黑盒测试)
设计测试用例方法之状态迁移法 一、状态迁移图 定义:通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为 案例: (1) 订机票案例1: l向航空公司打电话预定机票—>此时机票信息处于“完成”状…...
无涯教程-JavaScript - IMPRODUCT函数
描述 IMPRODUCT函数以x yi或x yj文本格式返回1到255个复数的乘积。两个复数的乘积为- $$(A BI)(C DI)(AC-BD)(A B)1 $$ 语法 IMPRODUCT (inumber1, [inumber2] ...)争论 Argument描述Required/OptionalInumber11 to 255 complex numbers to multiply.Required[inumbe…...
yapi以及gitlab的容器化部署
yapi部署: https://blog.csdn.net/Chimengmeng/article/details/132074922 gitlab部署 使用docker-compose.yml version: 3 services: web: image: twang2218/gitlab-ce-zh:10.5 restart: always hostname: 192.168.xx.xx environm…...
TCP、UDP 协议的区别,各自的应用场景
分析&回答 TCP 传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能&…...
C高级 DAY3
一、shell中的变量 shell本身是擅长运行指令,是一种弱数据类型语言 它与c语言中定义变量有所不同 C中: 存储类型 数据类型 变量名;shell中: 变量变量的值 ----->如果变量的值中间没有空格直接使用 变量变量的值 ----->变量…...
Linux CentOS7命令及命令行
Linux CentOS7中命令及命令行是非常重要的概念。对大多数初学者来说是既熟悉又了解甚少。本文初步讨论这方面的内容,与同行者交流。 一、命令 命令又称为指令,(英语命令 command,可用简写cmd表示),在终端…...
【C++入门到精通】C++入门 ——搜索二叉树(二叉树进阶)
阅读导航 前言一、搜索二叉树简介1. 概念2. 基本操作⭕搜索操作🍪搜索操作基本代码(非递归) ⭕插入操作🍪插入操作基本代码(非递归) ⭕删除操作🍪删除操作基本代码(非递归࿰…...
学成在线-网站搭建
文章目录 代码素材来自b站pink老师 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>学成在线首…...
stm32同芯片但不同flash工程更换Device出现报错
目录 1. 问题描述2. 解决方案 1. 问题描述 stm32同芯片但不同flash工程更换Device出现报错 2. 解决方案 更换Device,我是从ZE换为C8: 把这个从HD更换为MD 解决!...
Element UI实现每次只弹出一个Message消息提示
前言 在开发Web应用程序时,我们经常需要使用消息提示来向用户展示重要信息。Element UI提供了一个方便易用的组件——Message,可以用于显示各种类型的消息提示。 然而,默认情况下,当多个消息提示同时触发时,它们会依…...
「网页开发|前端开发|Vue」04 快速掌握开发网站需要的Vue基础知识
本文主要介绍使用Vue进行前端开发的一些必备知识,比如:Vue应用实例,Vue的组件概念,模板语言和模板语法,计算属性,路由配置等等。 文章目录 本系列前文传送门前言一、Vue实例:项目入口二、模板语…...
解决Redis分布式锁主从架构锁失效问题的终极方案 含面试题
面试题分享 2023最新面试合集链接 2023大厂面试题PDF 面试题PDF版本 java、python面试题 项目实战:AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 史上最全文档AI绘画stab…...
建站系列(三)--- 网络协议
目录 相关系列文章前言一、定义二、术语简介三、协议的组成要素四、网络层次划分五、常见网络协议划分六、常用协议介绍(一)TCP/IP(二)HTTP协议(超文本传输协议)(三)SSH协议 相关系列…...
jetson orin nx无显示器启动
sudo apt-get install xserver-xorg-core-hwe-18.04 sudo apt-get install xserver-xorg-video-dummy在 /usr/share/X11/xorg.conf.d/ 中添加 xorg.conf 文件。 Section "Monitor"Identifier "Monitor0"HorizSync 28.0-80.0VertRefresh 48.0-75.0Modeline…...
【APUE】标准I/O库
目录 1、简介 2、FILE对象 3、打开和关闭文件 3.1 fopen 3.2 fclose 4、输入输出流 4.1 fgetc 4.2 fputc 4.3 fgets 4.4 fputs 4.5 fread 4.6 fwrite 4.7 printf 族函数 4.8 scanf 族函数 5、文件指针操作 5.1 fseek 5.2 ftell 5.3 rewind 6、缓冲相关 6.…...
es6---模块化
main.js import { bar } from "./module1"; import module2 from "./module2"; bar() module2()module1.js // 多变量导出,导入变量需要变量名一对一映射 export const module1module1 export function bar(params) {console.log(module1) }m…...
【项目 计网12】4.32UDP通信实现 4.33广播 4.34组播 4.35本地套接字通信
文章目录 4.32UDP通信实现udp_client.cudp_server.c 4.33广播bro_server.cbro_client.c 4.34组播multi_server.cmulti_client.c 4.35本地套接字通信ipc_server.cipc_client.c 4.32UDP通信实现 udp_client.c #include <stdio.h> #include <stdlib.h> #include <…...
创建简单的 Docker 数据科学映像
推荐:使用NSDT场景编辑器快速搭建3D应用场景 为什么选择 Docker for Data Science? 作为一名数据科学家,拥有一个标准化的便携式分析和建模环境至关重要。Docker 提供了一种创建可重用和可共享的数据科学环境的绝佳方法。在本文中ÿ…...
网站建设服务器维护内容/百度seo优化关键词
修改器介绍修改器介绍修改器和获取器相反,修改器的主要作用是对模型设置的数据对象值进行处理。修改器方法的命名规范为:setFieldNameAttr修改器的使用场景和读取器类似:1.时间日期字段的转换写入;2.集合或枚举类型的写入…...
学做包子馒头的网站/可以营销的十大产品
读写分离 何为读写分离? 见名思意,根据读写分离的名字,我们就可以知道:读写分离主要是为了将对数据库的读写操作分散到不同的数据库节点上。 这样的话,就能够小幅提升写性能,大幅提升读性能。 我简单画了…...
网站开发的后台技术/商丘优化公司
scratch3.0中我们通过添加“朗读文字”扩展便可以编写程序,将文字朗读出来。那么如何编程,让Python将文字转成语音并读出来?方法比较多,我们在此先介绍一种(利用系统内置语音引擎实现发音),其他方法大家可以网上找到答…...
个人博客网站建设/搜狗网站收录
转:https://www.cnblogs.com/qyit/archive/2011/11/21/2257687.html 一个手柄/键盘映射程序,无外乎就四部分:一、界面;二、接收;三、处理;四、输出。 界面就不多说了。 接收,就是接收手柄的输出…...
深圳企业建站高性价比的选择/优化大师下载
随着flv格式的日益流行,越来越多的地方都在使用这个格式,体积小,是最大的优势,但是问题是 如果你手头是其他的视频格式 要转换为flv格式的话,是不是很头疼啊 。 当你看到这篇文章是,想必一定也在为 怎么把s…...
wordpress 付费下载插件/网络推广一个月工资多少
CentOS 7.x 虚拟机静态网络配置 修改主机名: hostnamectl set-hostname 主机名更改前: vim /etc/sysconfig/network-scripts/ifcfg-ens33更改后: TYPE“Ethernet” PROXY_METHOD“none” BROWSER_ONLY“no” BOOTPROTO“static” DEFROU…...