我与C++的爱恋:隐式类型转换


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

🔥个人主页guoguoqiang. 🔥专栏我与C++的爱恋

Alt

朋友们大家好,本篇内容我们来介绍初始化列表,隐式类型转换以及explicit的内容

一、初始化列表

1.1 构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值

class Date { public: Date(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };
​虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

1.2 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date
{
public:Date(int year=1900, int month=2, int day=2){_n = 10;_year = year;_month = month;_day = day;
}
private:int _year;int _month;int _day;const int _n;
};

在这里插入图片描述
我们发现const成员变量并不能用函数体进行初始化
int _year;
int _month;
int _day;
这三个成员既可以在函数体,又可以在初始化列表。
但是类中有的成员必须放在初始化列表位置进行初始化:
1.const 成员变量
2.引用成员变量
3.自定义类型成员(且没有默认构造函数)

int _year;
int _month;
int _day;
const int _n;

这个是声明,定义是对象实例化的时候完成的,有些成员必须在定义的时候初始化。

class Date
{
public:Date(int year, int month, int day):_n(1),_year (year),_month(month),_day (day){}
private:int _year;int _month;int _day;const int _n;
};

初始化列表是每个成员变量定义初始化的地方

class Date2 {
public:Date2(int year, int month, int day)	:_n(1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;const int _n;
};

不管你写不写每个成员都要走初始化列表。没有在初始化列表中显式初始化_year、_month、和_day这三个成员变量,它们仍然会在初始化列表阶段被默认初始化,然后在构造函数体内被赋新的值
所有的成员,你可以在初始化列表初始化,也可以在函数体内部初始化。

我们之前也说到过缺省值,声明时给初始值。

private:int _year=2024;int _month;int _day;const int _n;

缺省值的本质是给初始化列表。
在这里插入图片描述

尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
引用类型必须在定义的时候初始化,所以也得使用初始化列表

class A {
public:A(int a = 0): _a(a){}
private:int _a;
};
class Date
{
public:Date(int year, int month, int day):_n(1), _year(year), _month(month), _day(day), _ref(x){}
private:int _year=1;int _month;int _day;const int _n;int& _ref;A aa;
};
int main() {Date d2(2024, 4, 20);return 0;
}

成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

class A
{
public:A(int a):_a1(a),_a2(_a1){}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a2;int _a1;
};
int main() {A aa(1);aa.Print();
}

这个结果是什么呢?
在这里插入图片描述
我们发现a1是1而a2是随机值,成员变量的初始化顺序是由它们在类中的声明次序决定的。与其在初始化列表中的先后次序无关。
在A类中_a2比_a1先声明,因此_a2会先于_a1初始化。

应该按照成员变量在类中声明的顺序初始化它们,或者更改成员变量的声明顺序以反映期望的初始化顺序。

class A
{
public:A(int a):_a1(a)//现在是_a1先初始化,_a2(_a1)//然后_a2再初始化{}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a1;//声明顺序改为先_a1int _a2;//后_a2
};
int main() {A aa(1);aa.Print();
}

在这里插入图片描述

1.3 隐式类型转换

class A
{
public:A(int a):_a1(a){}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a1;
};
int main() {A aa1(1);aa1.Print();A aa2=2;aa2.Print();
}

在这里插入图片描述
构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。这个构造函数允许构造函数参数类型到类类型的隐式类型转换。这种转换使得单个值可以被视为是该类的一个实例,即使没有显式地调用构造函数。

class A
{
public:A(int a):_a1(a){}void Print() {cout << _a1<< endl;}
private:int _a1;
};
int main() {A aa2 = 2;A& aa2 = 3;aa2.Print();
}

A& aa2 = 3;试图将一个整型字面量3赋给A类型的引用aa2。这行代码会导致编译错误,原因如下:

  1. 引用的基本要求:在C++中,引用必须绑定到一个已经存在的对象上。引用本质上是对象的别名,它不能像指针那样独立存在
  2. 引用与临时对象:临时变量具有常性,在引用前应该加const(const A& aa2)
    正确用法:
    const A& aa1=A(3);//或者const A& aa2 = 3;
A aa3(4);
A& aa4=aa3;
class Stack
{
public:void Push(const A& a){//}
};

压栈

Stack st;
A aa3(3);
st.Push(aa3);st.Push(4);

直接用隐式类型转换就方便了很多

1.4 explicit关键字

如果不想让隐式类型转换发生,我们就需要用 explicit修饰构造函数,禁止类型转换在这里插入图片描述
在这里插入图片描述
单参构造函数,没有使用explicit修饰,具有类型转换作用
C++11及以后版本版本支持多个参数隐式类型转换

class A
{
public://explicit A(int a1, int a2)A(int a1, int a2):_a1(a1),_a2(a2){}private:int _a1;int _a2;
};
int main()
{A aa={1,2};return 0;
}

如果不想让隐式类型转换发生可以加上explicit关键字。

感谢大家观看!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

说说redis的数据类型

1.字符串&#xff08;String&#xff09;&#xff1a;其存储二进制的数据&#xff0c;对数据可以进行原子性的增加或者减少操作 2.List&#xff08;列表&#xff09;&#xff1a;按照插入顺序进行排序&#xff0c;可以进行元素的重复&#xff0c;可以对列表的两端进行插入或者删…

etcd campaign

1. 引言 本文主要讲解使用etcd进行选举的流程&#xff0c;以及对应的缺陷和使用场景 2. etcd选举流程 流程如以代码所示&#xff0c;流程为&#xff1a; clientv3.New 创建client与etcd server建立连接 concurrency.NewSession 创建选举的session&#xff0c;一般会配置ses…

java:Java中的接口

什么是接口 概念&#xff1a; 官方解释&#xff1a;Java接口是一系列方法的声明&#xff0c;是一些方法特征的集合&#xff0c;一个接口只有方法的特征没有方法的实现&#xff0c;因此这些方法可以在不同的地方被不同的类实现&#xff0c;而这些实现可以具有不同的行为&#x…

Java Maven项目推送到 Maven 中央仓库

准备阶段 namespace 域名认证 当需要在 sonatype 认证 com.xxx命名空间时&#xff0c;需要将 .xxx.com 配置域名解析。 记录类型&#xff1a;TXT 文本内容&#xff1a;验证的 key。 GPG 公私钥生成 GPG 下载地址&#xff1a;https://www.gnupg.org/download/index.html M…

零代码编程:用kimichat将mp4视频批量转为mp3音频

一个文件夹里面有多个子文件夹&#xff0c;里面的视频需要转成为mp3音频格式。可以在kimichat中键入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个Python脚本的编写任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;D:\CHATGPT For TikT…

openAI介绍及相关概念

OpenAI 简介 成立背景: OpenAI 成立于 2015 年&#xff0c;由一群高科技界的重要人物创立&#xff0c;包括 Elon Musk 和 Sam Altman。其目标是推动人工智能&#xff08;AI&#xff09;的发展&#xff0c;同时确保 AI 的发展能够造福全人类。 研究方向: OpenAI 专注于深度学习…

新手必犯的十大错误 Python语言

Python 是一种广泛使用的编程语言&#xff0c;它以其简洁和易读性而闻名。然而&#xff0c;即使是经验丰富的程序员也可能会遇到一些常见的错误。以下是一些常见的 Python 错误案例&#xff1a; 语法错误&#xff08;SyntaxError&#xff09;&#xff1a; print("Hello Wo…

SpringBoot中异步执行事务REQUIRED和REQUIRED_NEW的区别

springboot中事务的使用方式 在spring的bean中&#xff0c;要开启数据库事务只需要在方法中标注注解 Transactional 注解常用的参数有 Class[] rollbackFor() default {} 指定回滚异常Propagation propagation() default Propagation.REQUIRED 事务的传播机制Isolation iso…

Hive:GROUP BY GROUPING SETS

分组聚合 group by x1, x2, x3 grouping sets((x1), (x1, x2), (x1, x3),(x1, x2, x3)) 将不同维度的GROUP BY结果进行UNION ALL操作 GROUPING SETS会把在单个GROUP BY逻辑中没有参与GROUP BY的那一列置为NULL值&#xff0c;这样聚合出来的结果&#xff0c;未被GROUP BY的列…

web server apache tomcat11-10-Class Loader

前言 整理这个官方翻译的系列&#xff0c;原因是网上大部分的 tomcat 版本比较旧&#xff0c;此版本为 v11 最新的版本。 开源项目 从零手写实现 tomcat minicat 别称【嗅虎】心有猛虎&#xff0c;轻嗅蔷薇。 系列文章 web server apache tomcat11-01-官方文档入门介绍 web…

AI推介-多模态视觉语言模型VLMs论文速览(arXiv方向):2024.04.10-2024.04.15

文章目录~ 1.Photo-Realistic Image Restoration in the Wild with Controlled Vision-Language Models2.Do LLMs Understand Visual Anomalies? Uncovering LLM Capabilities in Zero-shot Anomaly Detection3.UNIAA: A Unified Multi-modal Image Aesthetic Assessment Base…

大华相机C#学习之Enumerator类

构造函数 Enumerator() 创建一个Enumerator实例。 常用方法 EnumerateDevices() 枚举所有发现设备,返回List<IDeviceInfo>对象。 List<IDeviceInfo> devices new List<IDeviceInfo>();private void test_Click(object sender, EventArgs e) {devicesEnum…

【Spring进阶】基于注解的面向切面编程(AOP)详解

hi&#xff0c;我是程序员王也&#xff0c;一个资深Java开发工程师&#xff0c;平时十分热衷于技术副业变现和各种搞钱项目的程序员~&#xff0c;如果你也是&#xff0c;可以一起交流交流。 今天我们聊一聊Spring中的AOP~ AOP的核心概念 面向切面编程&#xff08;AOP&#xff…

如何实现redis的高可用?

1.主从模式&#xff1a;就是一个住节点&#xff0c;多个从节点&#xff0c;但是弊端是一个主节点崩了&#xff0c;需要手动的切换从节点&#xff0c;这个挺麻烦的 2.哨兵模式&#xff1a;就是为了解决主从模式的弊端从而在主从模式的基础上加了哨兵&#xff0c;从而可以实现自动…

【一】ECharts----【基本概念、基本实例】

目录 零.前言 一.ECharts的安装 1.1独立版本的安装 1.2CDN的安装 1.3NPM的安装 二.ECharts实例 三.系列(series) 四.创建一个ECharts图表的基本步骤 4.1创建一个DOM容器 4.2使用DOM节点初始化ECharts对象 4.3设置配置信息 4.3.1图表标题 4.3.2提示信息 4.3.3图例组…

90天玩转Python—18—Python面向对象编程:核心概念详解

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

提取点云-------PCL

提取点云 /// <summary> /// VoxelGrid滤波下采样 /// </summary> /// <param name"cloud">需要滤波的点云</param> /// <param name"lx">三维体素栅格的x</param> /// <param name"ly">三维体素栅格…

全新Linux教程-驱动大全-PCI和PCIe子系统-P2-PCI设备的访问方法-非桥设备

主要讲PCI设备的硬件访问方法。 1、PCI的硬件结构 CPU发出的地址是CPU地址&#xff0c;可能是访问底下任何一个设备。地址范围不一样&#xff0c;访问到的外设就不一样。在嵌入式中&#xff0c;通常将4G内存地址空间分成好几个区域&#xff0c;不同的访问分给不同的地址。桥内…

Github首页美化(updating)

Github首页美化 一、新建仓库二、美化Github首页主页访问量统计仓库状态统计常用语言占比统计社交链接 界面展示 一、新建仓库 对Github首页进行美化&#xff0c;需要新建一个仓库名和自己 Github 用户名相同的仓库&#xff1b;并且需要添加一个 README.md自述文件即可。 如果…

nVisual在线网络规划设计软件

●01● nVisual在线网络规划设计软件 在信息化快速发展的今天&#xff0c;网络基础设施的建设与优化变得尤为关键。为了满足现代通信行业对高效、精准的网络规划需求&#xff0c;nVisual在线网络规划设计软件应运而生&#xff0c;它通过集成先进的GIS技术和网络规划工具&#…