【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、内部类默认是外部类的友元

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MPI之虚拟进程拓扑

什么是虚拟进程拓扑 在很多并行应用进程中,进程的线性排列不能充分的反映进程间在逻辑上的通信模型,通常由问题几何和所用的算法决定,进程经常被排列成二维或者三维网络形式的拓扑模型而通常用一个图来描述逻辑进程排列,此种逻辑…

SpringBoot入门篇3 - 整合junit、整合mybatis、基于SpringBoot实现ssm整合

目录 1.整合JUnit Spring整合JUnit SpringBoot整合JUnit 测试类注解:SpringBootTest 作用:设置JUnit加载的SpringBoot启动类 2.整合mybatis ①使用spring initializr初始化项目的时候,添加依赖。 ②设置数据源application.yml spring:d…

第 112 场 LeetCode 双周赛题解

A 判断通过操作能否让字符串相等 I s 1 s1 s1和 s 2 s2 s2第 1 1 1、 2 2 2位若同位置不等,则 s 1 s1 s1交换对应的 i i i和 j j j位置,之后判断 s 1 s1 s1和 s 2 s2 s2是否相当 class Solution { public:bool canBeEqual(string s1, string s2) {for (i…

低代码与低代码平台的概念解析

随着数字化转型和软件需求的不断增长,传统的手写代码开发方式已经无法满足迅速推出应用程序的需求。为了加快软件开发的速度并降低技术门槛,低代码开发模式应运而生。本文将介绍低代码的概念,探讨什么是低代码什么是低代码平台? 一…

8.react18并发模式与startTransition(搜索高亮思路)

React 18 之前,渲染是一个单一的,不间断的,同步的事务,一旦渲染开始,就不能被中断 React 18引入并发模式,它允许你将标记更新作为一个transitions,这会告诉React他们可以被中断执行.这样可以将紧急任务先更新,不紧急任务后更新. 将任务给紧急任务先执行, 优先级低的任务后执行…

JavaScript原型链污染

JavaScript原型链污染 一、什么是原型链污染(JS)二、前置知识2.1 JS对象2.11 通过类创建2.12 字面量模式创建2.13构造函数模式创建 2.2 默认属性 三、污染利用 一、什么是原型链污染(JS) 原型链污染(Prototype Pollution)是一种安全漏洞,在 …

零基础搭建个人影音媒体平台,实现远程访问Jellyfin播放器的简易方法

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…

VBA中如何将if写到一行

在VBA中,可以使用以下两种方式来编写一行if语句: 使用三元运算符: Dim result As String result "Yes" If True Else "No"在这个例子中,如果条件为真,则result变量的值为"Yes"&#…

抖音小程序开发教学系列(1)- 抖音小程序简介

章节一:抖音小程序简介 1.1 抖音小程序的背景和概述 抖音小程序的发展背景和市场趋势: 抖音作为一款热门的短视频社交平台,用户群体庞大,社交共享的特性也为小程序的发展提供了广阔的空间。抖音小程序作为抖音在社交和用户粘性…

质谱技术对蛋白质进行鉴定

参考B站教学视频: 质谱如何鉴定蛋白质_哔哩哔哩_bilibili 针对该视频,别人的 笔记 质谱是一台体重秤,称的不是人,而是分子、原子的体重 不同分子有不同分子量是质谱仪工作的底层逻辑 图片来自:【蛋白组】蛋白质组定量技术的原理和…

HTML+JavaScript+CSS DIY 分隔条splitter

一、需求分析 现在电脑的屏幕越来越大,为了利用好宽屏,我们在设计系统UI时喜欢在左侧放个菜单或选项面板,在右边显示与菜单或选项对应的内容,两者之间用分隔条splitter来间隔,并可以通过拖动分隔条splitter来动态调研…

GaussDB数据库SQL系列-行列转换

一、前言 二、简述 1、行转列概念 2、列转行概念 三、GaussDB数据库的行列转行实验示例 1、行转列示例 1)创建实验表(行存表) 2)静态行转列 3)行转列(结果值:拼接式) 4&…

maven部署

一、下载Maven 地址:Maven – Download Apache Maven 二、解压缩,设置环境变量 tar -xvf apache-maven-3.8.8-bin.tar.gz export MAVEN_HOME/opt/apache-maven-3.8.8 export PATH$MAVEN_HOME/bin:$PATH echo $MAVEN_HOME echo $PATH mvn -v

Android AGP版本

做个记录: Android AGP版本 https://developer.android.com/studio/releases/gradle-plugin?hlzh-cn

mac idea启动没反应 无法启动

遇到的问题如下: 启动idea,没反应 无法启动,不论破解还是别的原因,总之无法启动了 应用程序–找到idea–右击显示包内容–Contents–MacOS–打开idea 弹出框提示如下: 双击这个idea可执行文件 1)先查看日志…

Kafka3.0.0版本——Leader故障处理细节原理

目录 一、服务器信息二、服务器基本信息及相关概念2.1、服务器基本信息2.2、LEO的概念2.3、HW的概念 三、Leader故障处理细节 一、服务器信息 三台服务器 原始服务器名称原始服务器ip节点centos7虚拟机1192.168.136.27broker0centos7虚拟机2192.168.136.28broker1centos7虚拟机…

docker安装grafana,prometheus,exporter以及springboot整合详细教程(GPE)

springboot项目ip:192.168.168.1 测试服务器ip:192.168.168.81 文章来自互联网,自己略微整理下,更容易上手,方便自己,方便大家 最终效果: node springboot 1.下载镜像 docker pull prom/node-exporter docker pull prom/mysqld-exporter docker pull google/cadvisor dock…

「黄钊的AI日报·第一季」免费试读!最后5天,早鸟价60元~

1、每天5条AI内容点:不是常见的新闻汇总模式,而是站在AI产品经理的视角,把每篇AI干货的最核心内容,直接拎出来、甚至用自己的话来描述,是在展示“what I see”,和原文已经不是一个东西了! 2、已…

MIT6.824 Spring2021 Lab 1: MapReduce

文章目录 0x00 准备0x01 MapReduce简介0x02 RPC0x03 调试0x04 代码coordinator.gorpc.goworker.go 0x00 准备 阅读MapReduce论文配置GO环境 因为之前没用过GO,所以 先在网上学了一下语法A Tour of Go 感觉Go的接口和方法的语法和C挺不一样, 并发编程也挺有意思 0x01 MapRed…

OpenAI推出ChatGPT企业版,提供更高安全和隐私保障

🦉 AI新闻 🚀 OpenAI推出ChatGPT企业版,提供更高安全和隐私保障 摘要:OpenAI发布了面向企业用户的ChatGPT企业版,用户可以无限制地访问强大的GPT-4模型,进行更深入的数据分析,并且拥有完全控制…