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

【C++笔记】C++之类与对象(下)

【C++笔记】C++之类与对象(下)

  • 1、再看构造函数
    • 1.1、构造函数的初始化列表
    • 1.2、C++支持单参数的构造函数的隐式类型转换
    • 1.3、匿名对象
  • 2、Static成员
    • 2.1、为什么要有静态成员变量?
    • 2.2、一个类的静态成员变量属于这个类的所有对象
    • 2.3、静态成员函数
  • 3、友元
    • 3.1、友元函数
    • 3.2、友元类
  • 4、内部类
    • 4.1、内部类与外部类是互相独立的
    • 4.1、内部类默认是外部类的友元

1、再看构造函数

1.1、构造函数的初始化列表

为什么要引入初始化列表呢?
我们之前知道,在编译器自动生成的构造函数中,对于自定义类型会去调用其默认构造函数,但要是这个自定义类型没有可用的默认构造函数,就会出问题了,例如:
在这里插入图片描述
这时候先要解决这个问题,就要用到初始化列表了,因为在初始化列表中就可以对这个b进行定义。

初始化列表的语法如下图所示:
在这里插入图片描述
也就是初始化列表是在构造函数的大括号之前,以冒号开始以逗号分隔每个成员的值用括号定义。

初始化列表是每个成员定义的地方:
初始化列表是每个成员定义的地方,所以有了初始化列表之后,在就如构造函数的函数体之前就会去走初始化列表,然后再去走函数体。
我们通过调试就可以看出:
在这里插入图片描述
在这里插入图片描述
事实上,不管你写不写每个成员都要走初始化列表,这个我们可以通过为成员加上缺省值来验证,因为成员的缺省值就是给初始化列表用的:
在这里插入图片描述
可以看到,虽然我们并没有在初始化列表里面写上_month的定义,但是当走到_day的定义的时候,_month就已经定义成了我们所给的缺省值了。这就说明了_month其实也走了初始化列表。
其实在走完_year时,编译器是会自动跳到成员列表处去定义_month的:
在这里插入图片描述
正是因为不管怎样,每个成员都会走初始化列表,所以我们以后可以用初始化列表就尽量要用初始化列表。
初始化列表初始化的顺序和声明的顺序相同:
这个可以通过一个“反常”现象进行验证:
在这里插入图片描述
对于这个程序我们一般都会理解成,输出两个1,但是结果却不是这样。这其实就恰恰说明了初始化列表初始化的顺序是和声明的顺序是一样的,因为是a2先声明,所以初始化列表会先走a2的定义,但a1的只还是随机值。
所以就出现了以上的结果,只要我们改一下它们在初始化列表中的顺序,这程序就正常了:
在这里插入图片描述
所以为了避免出现各种问题,我们一般都要保证初始化列表初始化的顺序和声明的顺序一样。
而在吧编译器自动生成的构造函数中,其实是在初始化列表中对内置类型不作处理(假如没有给缺省参数),对于自定义类型则去调用其默认构造函数:
在这里插入图片描述

1.2、C++支持单参数的构造函数的隐式类型转换

C++之所以支持这个语法,主要还是能个好的应付自定义类型的一些场景,还是拿我们的栈来举例子,对于下面这个类,我们在定义对象的时候其实有两种写法:
在这里插入图片描述
这里的本质其实就是隐式类型转换,编译器会先用2去调用A的构造函数去生成一个临时对象,再用这个对象去拷贝构造a2。
但是编译器觉得先构造在拷贝构造太麻烦了,于是编译器就再次进行了优化,将拷贝构造省去,用2直接构造a2。
从下面的结果中我们也可以看到编译器只调用了构造函数:
在这里插入图片描述

1.3、匿名对象

在C语言中我们见过匿名结构体,在C++中也有一个匿名对象,即我们在定义对象的时候可以不给名字:
在这里插入图片描述

匿名对象的生命周期只在一行,我们可以通过加上析构函数来验证这一点:
在这里插入图片描述
我们会发现程序在运行下一行指令的时候,就会先去调用析构函数。
其实C++支持这个语法还是为了代码简便,例如我们现在有一个函数的参数是一个自定义类型,如果不支持匿名对象我们每次都要先定义一个有名对象再去传:
在这里插入图片描述
但是有了匿名对象之后,我们就可以直接传一个匿名对象了:
在这里插入图片描述

2、Static成员

2.1、为什么要有静态成员变量?

有时候我们可能会有这样的需求:统计一个类总共定义了对少个对象。
我们很容易会想到定义一个全局变量,然后再在构造函数和拷贝构造中让这个全局变量自加1:
在这里插入图片描述
但这个做法的缺点就在于全局变量的作用域太大了,很容易就会被修改,只要被外人一修改,这统计的就不对了。
所以为了解决这个问题,C++引入了静态成员变量:
在这里插入图片描述

2.2、一个类的静态成员变量属于这个类的所有对象

首先要说明的是静态成员变量并不在类里面,这一点可以通过计算类的大小来验证:
在这里插入图片描述
可以看到,A的大小为4,也就是说只计算了成员_a的大小,并没有计算N的大小。
实际上静态成员变量是存在于静态区的。

静态成员变量不能给缺省值,静态成员变量需要在类外边定义:
在这里插入图片描述
因为静态成员变量属于所有类,所以如果它是共有的,他就可以直接使用类作用限定符来访问,而其他成员变量就不可以:
在这里插入图片描述

2.3、静态成员函数

熟了静态成员变量,C++还有一个静态成员函数
静态成员函数没有this指针,所以静态成员函数不能访问非静态成员:
在这里插入图片描述
但是它可以自由的访问静态成员变量:
在这里插入图片描述
而且如上图所示,静态成员变量并没有this指针,所以在调用的时候也就不需要先有对象,直接是用来访问限定符突破类域即可。

3、友元

虽然在类里边我们可以随便访问成员变量而不受访问限定符的限制,但有些函数我们会发现将它写成成员函数会很奇怪,例如对日期我们需要使用运算符重载重载一个流插入运算符:
在这里插入图片描述
我们这好像写的没问题,但当我们去调用的时候却会发现问题了:
在这里插入图片描述
这里提示说未接收到参数,这是因为我们的顺序反了,我们知道非静态成员函数都会有一个隐藏的this指针,并且永远在第一位:
在这里插入图片描述
所以我们如果要调用,就需要这样:
在这里插入图片描述
这样就简直太奇怪了,而且使用起来也是真不习惯。
所以为了解决这个问题,我们就需要引入友元了。

3.1、友元函数

上面的这个问题主要是参数的顺序不对,所以我们可以考虑将其写成全局的,这样就可以随意安排参数的顺序了:
在这里插入图片描述
但是当我们在调用的时候却还是会出现问题:
在这里插入图片描述
因为这些成员都是私有的,我们不能够直接访问。

其实我们可以用一个简单的方法来解决,就是对应每一个成员都写一个共有的函数来返回对应成员的值:
在这里插入图片描述
但当成员有很多个的时候这种方法也不是很简便,所以我们就可以用到友元声明:
在这里插入图片描述
因为这里的友元函数仅仅只是个声明,所以写在任何地方都是可以的。
这样这个函数就可以直接访问这些成员了:
在这里插入图片描述

3.2、友元类

有时候我们需要在一个类里边定义另一个类的对象:
在这里插入图片描述
但是烦心的是我们并不能直接访问其成员,因为是私有的:
在这里插入图片描述
这时候我们就可以将Date类声明成A类的“友元类”,没错,友元不仅可以声明友元函数还可以声明友元类:
在这里插入图片描述
这样在Date类中就可以随意的访问A类中的成员了:
在这里插入图片描述
这其实和友元函数的作用是相同的。

但有一点需要注意:“友元”并不是相互的,就像这里只有Date类是A的友元类,但A并不是Date类的友元类,也就是说在A类中不可以直接访问Date类中的成员:
在这里插入图片描述

4、内部类

这就像结构体可以嵌套定义一样,类也可以嵌套定义:
在这里插入图片描述

4.1、内部类与外部类是互相独立的

“内部类”虽然名称叫做内部类,但事实上它本身却并不包含在外部类里,这一点我们可以通过计算类的大小来验证:
在这里插入图片描述
很明显这里A类的大小仅为4,如果要包含内部类的话至少也的是8才对。

但内部类受外部类的访问限定符的限制,比如内部类若是公有的我们就可以直接通过A的类作用限定符来定义对象:
在这里插入图片描述
如若是私有,就不能了:
在这里插入图片描述

4.1、内部类默认是外部类的友元

内部类的优势就是内部类默认是外部类的友元类,也就是说内部类可以直接访问到外部类的成员:
在这里插入图片描述
但上面也说过了,友元并不是相互的,所以外部类并不能直接访问内部类的成员:
在这里插入图片描述

相关文章:

【C++笔记】C++之类与对象(下)

【C笔记】C之类与对象(下) 1、再看构造函数1.1、构造函数的初始化列表1.2、C支持单参数的构造函数的隐式类型转换1.3、匿名对象 2、Static成员2.1、为什么要有静态成员变量?2.2、一个类的静态成员变量属于这个类的所有对象2.3、静态成员函数 3、友元3.1、…...

管理类联考——英语——实战篇——大作文——图表——动态图表——整体效果

动态图表模板 What is clearly presented in the above 图表类型 is that dramatic changes have taken place in 主题词1 from 年份1 to 年份2.During the period, there was a marked jump from 数字1 to 数字2 in 事物1,while that of 事物2 declined significantly from 数…...

threejs纹理加载三(视频加载)

threejs中除了能把图片作为纹理进行几何体贴图以外,还可以把视频作为纹理进行贴图设置。纹理的类型有很多,我们可以用不同的加载器来加载,而对于视频作为纹理,我们需要用到今天的主角:VideoTexture。我们先看效果&…...

VUE笔记(三)vue的语法

一、计算属性 1、计算属性的概念 计算属性是依赖于源数据(data或者属性中的数据),在元数据的基础上进行逻辑运算后得到的新的数据,计算属性要依赖于源数据,源数据数据变化计算属性也会变化 2、计算属性的语法 在vue2中使用computed这个选…...

探讨uniapp的路由与页面生命周期问题

1 首先我们引入页面路由 2 页面生命周期函数 onLoad() {console.log(页面加载)},onShow() {console.log(页面显示)},onReady(){console.log(页面初次显示)},onHide() {console.log(页面隐藏)},onUnload() {console.log(页面卸载)},onBackPress(){console.log(页面返回)}3 页面…...

咸鱼之王俱乐部网站开发

我的俱乐部 最新兑换码 *注意区分大小写,中间不能有空格! APP666 HAPPY666 QQ888 QQXY888 vip666 VIP666 XY888 app666 bdvip666 douyin666 douyin777 douyin888 happy666 huhushengwei888 taptap666 周活动 宝箱周 宝箱说明 1.木质宝箱开启1个…...

Electron+Vue3+TS 打包exe客户端

Electron Vue3 TS 实战 - 掘金 如果报错loaderContext.getOptions is not a function ts-loader版本不一致导致的问题。 解决方案:npm install ts-loader8.0.0 --save...

vue3范围选择组件封装

个人项目地址: SubTopH前端开发个人站 (自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面) SubTopH前端开发个人站…...

能被整除的数(容斥原理)

思路: (1)需求:求对于1~n中至少能被p1~pm至少1个整除的数的个数,由于都是质数,彼此互质,不需要进行质因子分解,根据容斥原理, res n/p1 n/p2 ... n/pm - n /(p1p2) -…...

Modbus转Profinet网关与流量变送器兼容转ModbusTCP协议博图配置

首先,我们需要明确电磁流量计的通信协议是Modbus,而西门子1200PLC的通信协议是Profinet。这两种协议在功能和特性上存在一定的差异,因此需要使用兴达易控Modbus转Profinet网关设备进行转换。兴达易控的XD-MDPN100是Profinet转ModbusTCP的网关…...

HLS实现CORDIC算法计算正余弦并上板验证

硬件:ZYNQ7010 软件:MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4 1、CORDIC算法计算正余弦 CORDIC算法详细分析网上有很多资料,它的原理是用一系列旋转去逼近目标角度,这一系列旋转的角度为 θ a r c t…...

高阶数据结构并查集

目录: 并查集的概念代码实现 LeetCode例题 并查集的概念 将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中反复遇到查询某一个元素属于那个集合的运算…...

WSL2连接不了外网怎么办?

某天忽然WLAN变成地球图标,上不了Internet,搞了半天网络适配器,仍然不行。回忆之前做过的操作,曾经运行过ZoogVPN,试着启动并连接,然后退出,WLAN神奇地恢复了连接,可以上Internet了。…...

【C/C++】探索内存对齐的奥秘与优势

目录 一,前言 二,什么是内存对齐? 三,内存对齐的原理 四,内存对齐的优势 五,如何实现内存对齐?(看这节就行) 1.使用 #pragma pack 来实现内存对齐的示例 七&#…...

leetcode分类刷题:滑动窗口(二、重复元素类型)

1、连续子数组、连续子串问题通常需要滑动窗口来求解,本篇文章对应的“二、重复元素类型”在此基础上对连续子数组、连续子串中重复元素个数、种类进行考察,此时,需要使用和维护哈希表进行左右指针的移动,因此这类题目对应的解法为…...

MySQL—buffer pool

一、buffer pool的介绍 Buffer pool是什么 一个内存区域,为了提⾼数据库的性能,数据库操作数据的时候,把硬盘上的数据加载到buffer pool,不直接和硬盘打交道,操作的是 buffer pool的数据,数据库的增删改查…...

《C和指针》笔记8: 枚举类型

枚举 (enumerated)类型就是指它的值为符号常量而不是字面值的类型,它们以下面这种形式声明: enum Jar_Type { CUP, PINT, QUART, HALF_GALLON, GALLON };这条语句声明了一个类型,称为Jar_Type。这种类型的变量按下列方式声明: e…...

Python爬虫框架之Selenium库入门:用Python实现网页自动化测试详解

概要 是否还在为网页测试而烦恼?是否还在为重复的点击、等待而劳累?试试强大的Selenium!让你的网页自动化测试变得轻松有趣! 一、Selenium库到底是什么? Selenium 是一个强大的自动化测试工具,它可以让你直…...

docker swarm 部署服务网络问题

docker swarm 服务部署问题 docker swarm 部署服务时可能会出现,启动服务特别慢的情况,甚至一个service 启动后,容器会长时间处于 preparing 状态,直到 状态切换成 running 状态后,才会启动下一个service。然后查询资…...

1.00001git源码clone后进行编译(带调试)

– 新建用户 useradd postgres passwd postgres – 用户加入sude组 先cd到/etc/sudoers目录下 由于sudoers文件为只读权限,所以需要添加写入权限,chmod uw sudoers vim sudoers 找到root ALL (ALL) ALL这一行,在下一行加入username ALL (A…...

OpenLayers 可视化之热力图

注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

测试markdown--肇兴

day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异&#xff…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...