C++中explicit详解

文章目录

      • 1. **防止隐式类型转换**
        • 示例1:没有使用`explicit`
        • 示例2:使用`explicit`
      • 2. **防止拷贝初始化**
        • 示例1:没有使用`explicit`
        • 示例2:使用`explicit`
      • 3. **防止隐式类型转换的链式调用**
        • 示例1:没有使用`explicit`
        • 示例2:使用`explicit`
      • 4. **防止隐式类型转换的歧义**
        • 示例1:没有使用`explicit`
        • 示例2:使用`explicit`
      • 总结

在C++中, explicit关键字用于修饰构造函数和转换运算符,其主要目的是防止隐式类型转换和拷贝初始化,从而提高代码的可读性和安全性。以下是 explicit的详细作用和使用场景:

1. 防止隐式类型转换

当构造函数被声明为explicit时,它不能用于隐式类型转换。这意味着不能通过单个参数的构造函数隐式地将一个类型转换为另一个类型。

示例1:没有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit构造函数int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {printMyClass(10); // 隐式调用 MyClass(int) 构造函数return 0;
}

在这个例子中,MyClass(int)构造函数是非explicit的,因此可以隐式地将int类型转换为MyClass类型。调用printMyClass(10)时,会隐式地调用MyClass(10)构造函数。

示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit构造函数int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {// printMyClass(10); // 错误:无法隐式调用 MyClass(int) 构造函数printMyClass(MyClass(10)); // 显式调用 MyClass(10) 构造函数return 0;
}

在这个例子中,MyClass(int)构造函数被声明为explicit,因此不能隐式地将int类型转换为MyClass类型。调用printMyClass(10)时,会报错,必须显式地调用MyClass(10)构造函数。

2. 防止拷贝初始化

explicit构造函数不能用于拷贝初始化,但可以用于直接初始化。

示例1:没有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit构造函数int value;
};int main() {MyClass obj = 10; // 拷贝初始化,隐式调用 MyClass(int) 构造函数return 0;
}

在这个例子中,MyClass(int)构造函数是非explicit的,因此可以用于拷贝初始化。

示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit构造函数int value;
};int main() {// MyClass obj = 10; // 错误:无法隐式调用 MyClass(int) 构造函数MyClass obj(10); // 直接初始化,显式调用 MyClass(int) 构造函数return 0;
}

在这个例子中,MyClass(int)构造函数被声明为explicit,因此不能用于拷贝初始化。必须使用直接初始化的方式显式调用构造函数。

3. 防止隐式类型转换的链式调用

explicit可以防止多个隐式类型转换的链式调用,从而避免潜在的错误。

示例1:没有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit构造函数int value;
};class YourClass {
public:YourClass(MyClass obj) : myObj(obj) {} // 非explicit构造函数MyClass myObj;
};int main() {YourClass obj = 10; // 隐式调用 MyClass(int) 和 YourClass(MyClass)return 0;
}

在这个例子中,MyClass(int)YourClass(MyClass)构造函数都是非explicit的,因此可以隐式地将int类型转换为MyClass类型,再将MyClass类型转换为YourClass类型。

示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit构造函数int value;
};class YourClass {
public:explicit YourClass(MyClass obj) : myObj(obj) {} // explicit构造函数MyClass myObj;
};int main() {// YourClass obj = 10; // 错误:无法隐式调用 MyClass(int) 和 YourClass(MyClass)YourClass obj(MyClass(10)); // 显式调用 MyClass(10) 和 YourClass(MyClass)return 0;
}

在这个例子中,MyClass(int)YourClass(MyClass)构造函数都被声明为explicit,因此不能隐式地进行类型转换。必须显式地调用构造函数。

4. 防止隐式类型转换的歧义

在某些情况下,多个构造函数可能导致隐式类型转换的歧义。使用explicit可以避免这种歧义。

示例1:没有使用explicit
class MyClass {
public:MyClass(int x) : value(x) {} // 非explicit构造函数MyClass(double x) : value(static_cast<int>(x)) {} // 非explicit构造函数int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {printMyClass(10); // 隐式调用 MyClass(int) 构造函数printMyClass(10.5); // 隐式调用 MyClass(double) 构造函数return 0;
}

在这个例子中,MyClass(int)MyClass(double)构造函数都是非explicit的,因此可以隐式地将intdouble类型转换为MyClass类型。

示例2:使用explicit
class MyClass {
public:explicit MyClass(int x) : value(x) {} // explicit构造函数explicit MyClass(double x) : value(static_cast<int>(x)) {} // explicit构造函数int value;
};void printMyClass(MyClass obj) {std::cout << obj.value << std::endl;
}int main() {// printMyClass(10); // 错误:无法隐式调用 MyClass(int) 构造函数// printMyClass(10.5); // 错误:无法隐式调用 MyClass(double) 构造函数printMyClass(MyClass(10)); // 显式调用 MyClass(int) 构造函数printMyClass(MyClass(10.5)); // 显式调用 MyClass(double) 构造函数return 0;
}

在这个例子中,MyClass(int)MyClass(double)构造函数都被声明为explicit,因此不能隐式地进行类型转换。必须显式地调用构造函数,避免了潜在的歧义。

总结

explicit关键字的主要作用是防止隐式类型转换和拷贝初始化,从而提高代码的可读性和安全性。在设计类时,如果某个构造函数或转换运算符不应该被隐式调用,应该使用explicit关键字进行修饰。

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

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

相关文章

代码部落 20250629 CSP-J复赛 模拟赛

网址&#xff1a;代码部落 一&#xff1a; 相濡以沫 β&#xff08;代码请自写&#xff09; 签到题&#xff0c;如果a[i]<a[i1] a[i]a[i1],反之&#xff0c;直接输出No 二 共同富裕&#xff08;代码请自写&#xff09; 签到题&#xff0c;用sort前缀和 如果最富有的个…

零基础学习RabbitMQ(5)--工作模式(1)

在前面的章节中我们简单介绍过一些RabbitMQ的工作模式&#xff0c;RabbitMQ共提供了七种工作模式进行消息传递&#xff0c;这里我们来详细介绍。 1. Simple(简单模式) P&#xff1a;生产者 C&#xff1a;消费者 特点&#xff1a;一个生产者一个消费者&#xff0c;消息只能被…

Android Liunx ffmpeg交叉编译

本文的交叉编译在window上安装VMware&#xff0c;使用Ubuntu20.4进行的编译。 一、安装NDK&#xff1a; 1、下载解压&#xff1a; 在NDK 下载 | Android NDK | Android Developers下载Liunx平台的NDK。 本人下载的是android-ndk-r27c-linux.zip版本的。 解压android-ndk-r…

极海G32R501双向数字电源解决方案 赋能AI服务器及电源应用创新

6月26日&#xff0c;Big-Bit商务网主办的2025中国电子热点解决方案创新峰会在东莞召开&#xff0c;峰会以“核心智变、能效跃迁”为主题&#xff0c;聚焦光储充、800V超充、AI服务器、BMS、智能汽车照明与汽车中小电机电控应用。 峰会期间&#xff0c;珠海极海半导体有限公司&a…

【修电脑的小记录】连不上网

问题概述 问题表现为&#xff1a;电脑连接网络后&#xff0c;显示已连接但无法上网。 环境信息&#xff1a; - DNS 修改无效&#xff0c;ping 外网&#xff08;8.8.8.8&#xff09;失败 - 尝试重置网络参数、多种命令无果 &#x1f50d; 排查过程 1. 执行以下命令重置网络&a…

QT中QSS样式表的详细介绍

转自个人博客 **Qt样式表&#xff08;Qt Style Sheets&#xff0c;简称QSS&#xff09;**是一种类似于HTML中的CSS&#xff08;层叠样式表&#xff09;的机制&#xff0c;用于自定义Qt应用程序的外观。通过QSS&#xff0c;开发者可以轻松地修改控件的外观&#xff0c;而无需更改…

Spring 依赖注入:官方推荐方式及最佳实践

Spring 依赖注入&#xff1a;官方推荐方式及最佳实践 你正在遭遇以下困境吗&#xff1f; 项目变大后&#xff0c;依赖关系像一团乱麻&#xff0c;牵一发而动全身&#xff1f;单元测试难如登天&#xff0c;被迫启动整个Spring容器&#xff1f;NullPointerException 总在运行时突…

javaweb听课笔记day1

MySQL数据模型 关系型数据库: 通过表来存储数据 关系型数据库是建立在关系模型基础上的数据库&#xff0c;简单说&#xff0c;关系型数据库是由多张能互相连接的二维表组成的数据库 优点: 都是使用表结构&#xff0c;格式一致&#xff0c;易于维护;使用通用的SQL语言操作…

《从量子奇境到前端优化:解锁卡西米尔效应的隐藏力量》

卡西米尔效应由荷兰物理学家亨德里克卡西米尔于1948年提出&#xff0c;它源于量子场论中“真空不空”的奇异观点。在传统认知里&#xff0c;真空是一片虚无&#xff0c;但量子理论指出&#xff0c;真空中充满了持续涨落的能量&#xff0c;即零点能。想象有两片中性的金属板被放…

【学习笔记】强化学习的数学原理

软活硬整&#xff0c;纳什又把RL翻出来讲了一遍&#xff0c;我以为是温故而知新&#xff0c;原来是在卖书。 不过温故而知新还是没啥毛病的。 PS&#xff1a;今天装Notepad时看到的&#xff0c;我还以为现在连用个Notepad都要给天线宝宝们捐款了。 文章目录 PART 11 overview…

深入“火星棒球数据API”:用数据解锁棒球世界的无限可能

在棒球运动日益数据化的今天&#xff0c;高效获取和处理海量比赛信息已成为球队制胜、媒体解读、球迷深入理解比赛的关键。“火星棒球数据API” 应运而生&#xff0c;成为连接棒球智慧与大数据技术的桥梁。本文将探讨这一API的核心价值、功能亮点及其如何重塑我们体验和分析棒球…

[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的校园服务平台管理系统,推荐!

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园服务平台管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据…

「Java EE开发指南」如何用MyEclipse创建一个WEB项目?(三)

在本文中&#xff0c;您可以找到有关WEB项目的信息。将了解&#xff1a; Web项目结构和参数Web开发生产力工具JSP代码完成和验证 这些特性在MyEclipse中可用。在上文中&#xff08;点击这里回顾>>&#xff09;&#xff0c;我们为大家介绍了Web开发效率工具、Web项目参数…

笨方法学python -练习6

程序&#xff1a; print("Mary had a little lamb.") print("Its fleece was white as {}.".format(snow)) print("And everywhere that Mary went.") print("." * 10) # what′d that do? end1 "C" end2 "h&qu…

【MySQL】Binlog文件占用空间比较大,如何清理

一、前言 在进行一次数据导入之后&#xff0c;发现服务器磁盘爆满&#xff0c;初步判断是数据库产生了大量binlog所致&#xff0c;接下来进行分析处理。 二、分析 1、查看磁盘空间 通过df -h命令&#xff0c;查看磁盘空间占用情况 2、查找占用文件或目录 通过命令&#xff1a;…

车载诊断架构 --- 非易失性存储器(NVM)相关设置项

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

C#: 输入对话框窗口函数

这是一个 C# 输入对话框函数&#xff0c;主要功能包括&#xff1a; 基础功能&#xff1a;创建带标题、提示文本和输入框的对话框&#xff0c;返回用户输入或空字符串&#xff08;取消时&#xff09; 增强特性&#xff1a; 支持必填项验证支持正则表达式格式验证实时错误提示与…

PCB工艺学习与总结-20250628

一、PCB板材 1、结构组成 基板:作为电路板的支撑体,通常由绝缘材料制成,如玻璃纤维或塑料。 导线:用于连接电路板上的各个元件,传输电流和信号。 元件:包括电阻、电容、电感、二极管、晶体管等,用于实现电路的各种功能。 焊盘:用于焊接元件引脚的金属片,确保元件…

VUE2与VUE3项目环境变量创建与使用区别

环境变量文件是项目中的.env开头的文件&#xff0c;如下图&#xff1a; 下图是VUE2.env文件中的配置&#xff0c;是以VUE_APP开头的 VUE_APP_PAGE_TITLE系统 VUE_APP_SERVICE_PREFIX/gateway/xxxxx在使用时 只需要 调用 process.env.VUE_APP_SERVICE_PREFIX 就可以获取到值 而…

php flush实时输出线上环境好使,本地环境等待一段时间后一次性输出结果的原因

近期对接deepseek接口时为了拥有较好的用户体验&#xff0c;等待答案返回时采用了flush分布输出&#xff0c;但是线上环境下可以正常分布输出&#xff0c;同样代码在本地总是等待许久后一次性出结果&#xff0c;排查许久&#xff0c;发现竟然是本地和线上不同的php加载模式导致…