C++相关概念和易错语法(7)(初始化列表、隐式类型转换、友元)

1.初始化列表

初始化列表是集成在构造函数里面的,对象在创建的时候一定会调用构造函数(就算不显式定义,也会自动生成并调用)。初始化列表就是这些对象的成员变量在创建的时候初始化的地方。

下面是使用的例子,可以先看看:

注意:这个格式只能是:冒号开始,逗号分隔,成员变量后只能用括号(包括对象、赋值变量),不能使用赋值=,内置类型括号内是什么赋值什么,自定义类型就用括号里的值调用它的构造函数

我们需要将这种写法和我们之前写的构造函数做对比:

这个特性在某些场景非常关键,在以下两种场景中必须使用初始化列表:

(1)有的变量只有在初始化的时候赋值,比如引用int&(不能出现空引用),const修饰的变量(常属性)

(2)当我们不显式实现构造函数时,编译器会自动生成默认构造函数,其中的规则有一条为——对于自定义类型会去调用它的默认构造。这里有个问题就是,如果这个自定义类型显式实现了一个带参数的构造函数,那么它无法生成默认构造,编译器是无法调用它的,这个时候就会报错。

下面是实例:

我们发现如果没有初始化列表,这两种情况是无解的。对于(1),不管我们怎么写构造函数,引用和const变量在创建时都无法被赋值。对于(2)更是如此,根本不支持在大括号里去调用构造函数,只有初始化的时候才可以。

2.缺省值和初始化列表的关系

之前我们就提到调用构造函数前会先走一遍缺省值,后续的调用本质上是一种覆盖。

更准确地说,缺省值是给初始化列表使用的。假设我们在成员变量声明处写了int _a = 1,如果我们没有自己写初始化列表,而是在函数体内写了_a = 2,那么当_a创建时会自动创建一个初始化列表,其中_a初始化时在初始化列表中赋的值就是缺省值,也就是_a(1),后续再进入函数体,将_a赋值为2。

值得注意的是初始化列表中对成员变量进行初始化的顺序是按照在类中声明的顺序进行的,而不是按照初始化列表中代码的顺序进行的,同样地,这些成员变量在空间中开辟的顺序就是按照声明顺序进行的。

如果我们成员变量中有自定义类型的对象,且这个自定义类型中有含参的构造函数,那么我们一定要显式实现这个初始化列表,否则一定会报错。

如果我们显式实现了初始化列表,如在初始化列表中写了_a(1),在成员变量声明处写了缺省值int _a = 2,这个时候在编译器创建变量并初始化时就会直接忽略我们声明处的缺省值。

初始化列表或者缺省值处我们可以自由地写表达式或者函数,都能实现我们想要的效果。

3.内置类型隐式转换成自定义类型

这是一个相对来说比较难理解的地方,我们所知的int、char、double、int*等可以转换成类的类型,如A a = 3。这里需要注意的是数组不是内置类型,它属于自定义类型(int []),因此如A a = "Hello"这种操作是不行的。

转换的实质:

默认生成拷贝构造是const A& tmp,有const修饰,也不需要担心默认的拷贝构造会被const拦截住

注意这里是我们的逻辑,而编译器会进行优化,实际并不是这样,后面会提及。

但是,不是所有的情况都可以实现隐式类型转换,是要看自定义类型的构造函数有几个参数来决定的。下面我分情况来讲解一下:

(1)无参的构造函数:不支持任何隐式类型转换

(2)含一个参数的构造函数:支持所有内置类型的转换,转换的规则就是创建一个临时的对象(这个对象具有常属性,里面成员变量的值不能修改),这个内置类型的值就作为它构造函数的参数传过去。

传的参数没有要求,遵循C语言内置类型之间的隐式类型转换规则。

(3)多个参数:支持所有内置类型的转换,但根据规则我们需要多个内置类型才能隐式转换成自定义类型,用大括号括起来。注意内置类型的数量要和构造函数的参数个数相同,除非有缺省值,这和我们之前遇到的构造函数的初始化类似。

不加=也是可以的,要学会识别。

当然,隐式类型转换也存在它的风险,如果我们不想发生隐式类型转换,可以在构造函数前面加上explicit修饰

注意隐式类型转化也可以嵌套,在有的情况下还是很好用的


#include <iostream>
using namespace std;

class A
{
public:
	A(int a = 0, int b = 0)
		:_a(a)
		,_b(b)
	{}

	int _a;
	int _b;
};

class B
{
public:
	B(int c, A d)
		:_c(c)
		,_d(d._a, d._b)
	{}

private:
	int _c;
	A _d;

};

int main()
{
	B b1 = { 1,{2,3} };

	return 0;
}

4.友元

就在上面的那段代码,我们会注意到A的_a和_b是共有的,如果是私有的,那么如何处理呢?

(1)友元类

首先像构造和析构函数这种特殊的函数没有返回值,不是标准的函数形式,所以无法使用友元函数。因此我们要使用友元类来处理这种情况。声明友元类后,A的友元B可以访问A的所有私有变量以及所有的函数。


#include <iostream>
using namespace std;

class A
{
	friend class B;

public:
	A(int a = 0, int b = 0)
		:_a(a)
		,_b(b)
	{}
private:
	int _a;
	int _b;
};

class B
{
public:
	B(int c, A d)
		:_c(c)
		,_d(d._a, d._b)
	{}

private:
	int _c;
	A _d;

};

int main()
{
	B b1 = { 1,{2,3} };

	return 0;
}

(2)友元函数

如果B类或全局的函数想要访问A类的私有成员,我们可以采用友元函数的方式,用friend+函数声明即可。一个函数可以是多个类的友元函数,访问的时候和普通函数相同。

要注意友元函数的几个特性:

a.友元函数不能用const修饰(规定)

b.在A声明的友元函数并不是A的成员函数,也没有this的概念

c.友元函数可以在类定义的任何地方声明(不受访问限制符private的作用)

(3)内部类

内部类和我们理解的成员变量不太一样,它是独立的,在计算sizeof的时候不会计算内部类的大小。其实内部类仅仅是受到类域的限制,表明它是这个外部类的专属类。

内部类默认就是外部类的友元,内部类可访问外部类的私有成员;但是外部类并不默认是内部类的友元函数,不能直接访问。


 

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

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

相关文章

CCIE-16-PIM

目录 实验条件网络拓朴实验环境实验目的 开始实验实验1&#xff1a;PIM-DM配置PIM域中的路由&#xff0c;开启PIM-DM组播路由功能&#xff0c;验证组播情况 实验2&#xff1a;PIM-SM&#xff08;静态RP&#xff09;配置PIM域中的路由&#xff0c;开启PIM-SM组播路由功能&#x…

3-内核开发-第一个字符设备模块开发案例

3-内核开发-第一个字符设备模块开发案例 目录 3-内核开发-第一个字符设备模块开发案例 (1) 字符设备背景介绍 (2) 简单版本字符设备模块 (3) 继续丰富我们的字符驱动模块&#xff0c;增加write,read 功能 (4) 编译执行验证 (5)总结 (6)后记 (7)参考 课程简介&#xff…

[Meachines][Easy]Crafty

Main $ sudo nmap -p- -sS -T4 10.10.11.249 发现25565端口是我的世界服务器端口 CVE-2021-44228: https://nodecraft.com/blog/service-updates/minecraft-java-edition-security-vulnerability在阿帕奇Log4j图书馆&#xff0c;广泛使用的记录框架&#xff0c;在Java应用程序…

一起Talk Android吧(第五百五十七回:如何获取文件读写权限)

文章目录 1. 概念介绍2. 使用方法3. 示例代码4. 内容总结各位看官们大家好,上一回中分享了一个Retrofit使用错误的案例,本章回中将介绍 如何获取文件读写权限。闲话休提,言归正转,让我们一起Talk Android吧! 1. 概念介绍 我们在本章回中说的文本读写权限是指读写手机中的…

0-1背包问题:贪心算法与动态规划的比较

0-1背包问题&#xff1a;贪心算法与动态规划的比较 1. 问题描述2. 贪心算法2.1 贪心策略2.2 伪代码 3. 动态规划3.1 动态规划策略3.2 伪代码 4. C语言实现5. 算法分析6. 结论7. 参考文献 1. 问题描述 0-1背包问题是组合优化中的一个经典问题。假设有一个小偷在抢劫时发现了n个…

CCF-CSP真题《202312-3 树上搜索》思路+c++满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 问题描述 试题编号&#xff1a;202312-3试题名称&#xff1a;树上搜索时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 题目背景 问题描述 输入格式 输出格式 样…

BioTech - 使用 Amber 工具 松弛(Relaxation) 蛋白质三维结构 (Python)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/137889532 Amber 工具在蛋白质 松弛(Relaxation) 过程中起着重要的作用。在分子动力学模拟中,蛋白质松弛是指模拟过程中蛋白质结构达到一个较为稳定的状态。这个过程通…

SQLite轻量级会话扩展(三十四)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite R*Tree 模块&#xff08;三十三&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 1. 引言 会话扩展提供了一种方便记录的机制 对 SQLite 数据库中某些表的部分或全部更改&#xff0c;以及 将这些…

视频质量评价 SSIM 算法详细介绍

SSIM SSIM(Structural Similarity Index Measure)是一种用于衡量两幅图像之间相似度的指标,是属于全参考视频质量评价算法范畴;它在图像质量评估领域得到了广泛的应用。SSIM是基于人类视觉系统的特性设计的,它考虑了图像的亮度、对比度和结构信息。SSIM的值范围在-1到1之…

xilinx 7系列FPGA时钟布线资源

7系列FPGA拥有多种时钟路由资源&#xff0c;以支持各种时钟方案和需求&#xff0c;包括高扇出、短传播延迟以及极低的偏斜。为了最佳地利用时钟路由资源&#xff0c;需要了解如何将用户时钟从PCB传递到FPGA&#xff0c;确定哪种时钟路由资源最优&#xff0c;然后通过利用适当的…

【数据结构|C语言版】单链表

前言1. 单链表的概念和结构1.1 单链表的概念1.2 单链表的结构 2. 单链表的分类3.单链表的实现3.1 新节点创建3.2 单链表头插3.3 单链表头删3.4 单链表尾插3.5 单链表尾删3.6 链表销毁 4. 代码总结4.1 SLT.h4.2 SLT.c4.3 test.c 后言 前言 各位小伙伴大家好&#xff01;时隔不久…

百科不全书之 docker记录

docker记录 1.参考文件2. Docker简介与虚拟机的区别 3. 安装Docker注意 Windows家庭版的要额外设置 4.使用5.docker与ROS 1.参考文件 参考视频&#xff1a;B站【GeekHour】Docker入门教程: 【GeekHour】30分钟Docker入门教程 2. Docker简介 Docker是一个用于构建运行 传送…

The C programming language (second edition,KR) exercise(CHAPTER 4)

E x c e r c i s e 4 − 1 Excercise\quad 4-1 Excercise4−1&#xff1a; #include <stdlib.h> #include <stdio.h> #include <string.h> int strindex(char s[],char t[]); int strrindex(char s[],char t[]);int main(void) {char s[100]"qwoulddf…

Java | Leetcode Java题解之第41题缺失的第一个正数

题目&#xff1a; 题解&#xff1a; class Solution {public int firstMissingPositive(int[] nums) {int n nums.length;for (int i 0; i < n; i) {while (nums[i] > 0 && nums[i] < n && nums[nums[i] - 1] ! nums[i]) {int temp nums[nums[i] …

yolov8实战第七天——pyqt5-yolov8实现车牌识别系统(参考论文(约7000字)+环境配置+完整部署代码+代码使用说明+训练好的模型)

基于 pyqt5-yolov8实现车牌识别系统,包括图片车牌识别,视频车牌识别,视频流车牌识别。 效果展示(图片检测,检测到的内容添加到历史记录): 效果展示(视频检测,视频车辆只会添加一条记录,下文更多实际应用中的优化策略): 基于YOLOv8和PyQt5的车牌识别系统设计与…

存储竞赛,角逐未来

随着人工智能&#xff08;AI&#xff09;和大数据驱动的海量数据需求&#xff0c;对存储技术的要求也在不断提高。在此背景下&#xff0c;各大存储芯片巨头之间的技术竞赛日益激烈。 在NAND闪存领域&#xff0c;企业关注的重点在于层数的突破。近日&#xff0c;《韩国经济日报》…

linux下编译c++程序报错“undefined reference to `std::allocator<char>::allocator()‘”

问题 linux下编译c程序报错“undefined reference to std::allocator::allocator()”。 原因 找不到c标准库文件。 解决办法 开始尝试给gcc指令添加-L和-l选项指定库路径和库文件名&#xff0c;但是一直不成功&#xff0c;后来把gcc改为g就可以了。

Stylus精讲:网页设计新境界【写作AI一键生成】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

SWCTF

easy_php 源码 <?php// flag is in flag.php highlight_file(__FILE__); ini_set(display_errors, 0); error_reporting(0);if (isset($_GET[myon1]) && isset($_GET[myon2]) && isset($_GET[myon3])) {$myon1 $_GET[myon1];$myon2 $_GET[myon2];$myon…

# Win10 打不开【本地组策略编辑器】解决方案

Win10 打不开【本地组策略编辑器】解决方案 段子手168 问题描述&#xff1a; 当在 WIN R 打开【运行】输入&#xff1a;gpedit.msc 打开【本地组策略编辑器】时&#xff0c;出现错误时&#xff0c; 或者在【计算机管理】中 没有【本地用户和组】这一项。 可以试一下以下方…