C++11之显式转换操作符-explicit

2023-11-01

系列文章

C++11之正则表达式(regex_match、regex_search、regex_replace)

C++11之线程库(Thread、Mutex、atomic、lock_guard、同步)

C++11之智能指针(unique_ptr、shared_ptr、weak_ptr、auto_ptr)浅谈内存管理

C++11之强制类型转换(static_cast,const_cast,dynamic_cast,reinterpret_cast)

C++11之Lanbda表达式(匿名函数)

C++11之右值引用:移动语义和完美转发(带你了解移动构造函数、纯右值、将亡值、右值引用、std::move、forward等新概念)

C++11之继承构造函数(using 声明)

C++11之委派构造函数



隐式类型转换

在C++中存在着一把双刃剑—隐式类型转型。好处是可以编写过多的构造函数,坏处是总会有一些意外情况并非程序员所愿。

场景1

下面分别实现了有无被explicit关键字修饰的类和函数。

#include <iostream>

using std::cout;
using std::endl;

class Rational1
{
public:
	Rational1(int n = 0, int d = 1):num(n), den(d)
	{
		cout << __func__ << "(" << num << "/" << den << ")" << endl;
	}

public:
	int num; // 被除数
	int den; // 除数
};

class Rational2
{
public:
	explicit Rational2(int n = 0, int d = 1) :num(n), den(d)
	{
		cout << __func__ << "(" << num << "/" << den << ")" << endl;
	}

public:
	int num; // 被除数
	int den; // 除数
};

void Display1(Rational1 r)
{
	cout << __func__ << endl;
}

void Display2(Rational2 r)
{
	cout << __func__ << endl;
}


int main()
{
	Rational1 r1 = 11;
	Rational1 r2(11);
	Rational2 r3 = 11; // error E0415
	Rational2 r4(11);

	Display1(1);
	Display2(2); // error  E0415
	return 0;
}

运行报错:这是因为Rationl2这个类没有对应int参数的构造函数。
在这里插入图片描述

在这里,并没有体现出explicit的优点,甚至觉得有它使得代码更加麻烦。但是我们必须要阻止那种带有歧义的隐式类型转换。

场景2

这里的例子来自C++11提案,但有一些细微的变动。定义了一个Ptr类,并实现了bool类型转换。这样我们就可以很方便使用if(p)来判断指针是否有效。但是带来的坏处就是支持Ptr对象的相加运算,例如 p + pd

#include <iostream>

using std::cout;
using std::endl;

template<class T>
class Ptr
{
public:
	Ptr(T* p) :m_p(p) {}
	operator bool() const
	{
		return m_p != nullptr ? true : false;
	}

private:
	T* m_p;
};

int main()
{
	int a = 11;
	Ptr<int> p(&a);

	if(p)
	{
		cout << "valid pointer." << endl; // 有效的指针
	}
	else
	{
		cout << "invalid pointer." << endl; // 无效的指针
	}

	Ptr<int> pd(0);

	cout << p + pd << endl; 
	cout << pd << endl;
	return 0;
}

运行结果:

valid pointer.
1
0

很明显这并不是我们想要的结果。这时我们只需要使用explicit关键字修饰到bool类型转换上就可以有效的防止这种”意外“发生。

在bool运算符重载中添加explicit

运行结果:
没有找到接受’Ptr(int>'类型左操作数的操作符(或者没有可接受的转换)。
在这里插入图片描述

场景3

这里定义了一个ConvertTo和Convertable类。在Convertable类中有一个显式转换到ConverTo类的方法。

#include <iostream>

using std::cout;
using std::endl;

class ConvertTo{};

class Convertabkle
{
public:
	explicit operator ConvertTo() const
	{
		return ConvertTo();
	}

};

void Func(ConvertTo ct)
{
	
}

int main()
{
	Convertabkle c;
	ConvertTo ct(c); 
	ConvertTo ct2 = c;  // 拷贝构造函数  error
	ConvertTo ct3 = static_cast<ConvertTo>(c);  // C++11的强制类型转换
	Func(c); // 拷贝构造函数 error

	return 0;
}

那么这样就会使得只有直接初始化或者使用强制类型转换才可以进行转换,不能再通过拷贝构造函数隐式转换了。

在这里插入图片描述

总结

1、从上面几个例子中,可以看出显示类型转换explicit关键字并没有完全禁止从源类型到目标类型的转换,只是不允许拷贝构造函数和隐式类型转换罢了。所以我们就不能通过复制发方式或者通过函数参数的形式进行从源类型到目标类型的转换
2、所以我们有必要在创建类时及时添加explicit关键字,禁止隐式类型转换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11之显式转换操作符-explicit 的相关文章

  • 为什么相同的代码在同一台计算机上的执行时间可能不同?

    我是 C 编程新手 我编写了代码并希望获得它的运行时 这就是我所做的 每次运行代码时 我都会得到不同的运行时值 这样对吗 或者我的代码有问题吗 int main int argc char argv time t start end sta
  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • 用 C++ 进行服装建模 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在编写一些软件 最终会绘制一个人体框架 可以配置各种参数 并且计划是在假人身上放置某种衣服 我研究
  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 使用Physics.Raycast 和Physics2D.Raycast 检测对象上的点击

    我的场景中有一个空的游戏对象 带有 2D 组件盒碰撞器 我将脚本附加到该游戏对象 void OnMouseDown Debug Log clic 但是当我点击我的游戏对象时 没有任何效果 你有什么想法 如何检测我的盒子碰撞器上的点击 使用光
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • 读取文件特定行号的有效方法。 (奖励:Python 手册印刷错误)

    我有一个 100 GB 的文本文件 它是来自数据库的 BCP 转储 当我尝试导入它时BULK INSERT 我在第 219506324 行上收到一个神秘错误 在解决此问题之前 我想看看这一行 但可惜的是我最喜欢的方法 import line
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • 如何从main方法调用业务对象类?

    我已将代码分为业务对象 访问层 如下所示 void Main Business object public class ExpenseBO public void MakeExpense ExpensePayload payload var
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良

随机推荐

  • 维金细说“virtualization”

    摘要 在这个时代下 虚拟化已经成为毋庸置疑的主角 虚拟化对生活的影响也是方方面面的 熟悉 网络虚拟化的朋友知道 这是一种基于软件的 抽象的 从物理元素中分离流量的一种方式 近年来 随着云计算和大数据的诞生和飞速发展 各种虚拟化技术也好似 雨
  • Python--遍历列表时删除元素的正确做法

    一 问题描述 这是在工作中遇到的一段代码 原理大概和下面类似 判断某一个元素是否符合要求 不符合删除该元素 最后得到符合要求的列表 a 1 2 3 4 5 6 7 8 for i in a if i gt 5 pass else a rem
  • javafx预览PDF

    第一种方法 调用其它可外部程序打开 Runtime getRuntime exec rundll32 url dll FileProtocolHandler new File C Program Files aaa 202306171607
  • 代码混淆不一定要花大价钱,Code Virtualizer也能轻松搞定!

    任何创建创新性应用程序 DLL或设备驱动程序的开发人员都希望将代码尽可能机密 以避免第三方公司 开发人员研究应用程序内的代码并为自己的利益而窃取代码 一些开发人员使用外部保护系统来打包应用程序并保护其免受攻击者的侵害 但是大多数时候 这些保
  • Flutter实现底部菜单栏+页面切换(BottomNavigationBar+PageVIew)

    需求 实现底部主页 我的两个菜单栏 实现和页面联动点击 滑动切换 需求 底部实现两个菜单 首页 我的 和页面实现滑动 点击切换联动 1 底部菜单栏 第一时间就想到了 Scaffold部件的属性 bottomNavigationBar bot
  • tensorflow2 tf2 PG算法 强化学习玩乒乓球

    使用确定性策略梯度玩乒乓球 网上很多案例抄写下来 实际使用发现都无法收敛 花了很多时间纠错 然后从parl提供的代码作为核心参考 收集了其他案例中的优点 自己在tensorflow2中实现了算法 并测试成功收敛 0 99累计奖励 0 01
  • 华为云云耀云服务器L实例评测|怎么搭建企业综合Web平台

    前言 记得2019年 公司搞混合云的时候 测试过多家公有云 其中就有华为云 因公司也在深圳 项目也比较急 我司业务上云经验又不足 华为官方获悉情况后 第二天就派了4人小团队到我司来交流 整个交流过程非常流畅 从华为云的优势 华为POP点到我
  • 三种交换方式:电路交换、分组交换、报文交换

    三种交换方式 电路交换 分组交换 报文交换 电路交换 当 n n n部电话需要两两相连时 需要 C n 2
  • pycharm更换python解释器(anaconda和python官网)

    找到pycharm的文件按钮 2 点击设置按钮 3 点击项目 再点击python解释器就会出现这个窗口了 4 笔者这里是conda解释器 如果是python官网安装的就要点第一个 然后就是找到python解释器的路径了 一般我们要找的是这个
  • Python输出列表(List)不带中括号和引号

    正常python输出列表List时 会自动加上中括号和引号 例如 gt gt gt list1 a b c d gt gt gt list1 a b c d 解决方法一 使用join gt gt gt print join list1 a
  • 第四届蓝桥杯国赛C++B组 空白格式化

    标题 空白格式化 本次大赛采用了全自动机器测评系统 如果你的答案与标准答案相差了一个空格 很可能无法得分 所以要加倍谨慎 但也不必过于惊慌 因为在有些情况下 测评系统会把你的答案进行 空白格式化 其具体做法是 去掉所有首尾空白 中间的多个空
  • 数学建模基本算法模型

    全国大学生数学建模竞赛中常用的算法模型包括但不限于以下几种 线性回归模型 用于建立变量之间线性关系的模型 常用于预测和分析数据 逻辑回归模型 用于建立变量之间的非线性关系 常用于分类问题和概率预测 决策树模型 将数据集分解成更小的数据集 并
  • Excise_Thread2

    1 下列关于多线程中锁机制正确的是 A 关键字synchronized只能用于方法声明上 B 成员方法使用synchronized 那么当前方法的锁对象为当前方法所属的对象 C 静态方法使用synchronized 那么当前方法的锁对象为当
  • 【已解决】Nacos配置出现错误:Error creating bean with name‘memoryMonitor‘

    Nacos版本2 2 3 可先参考这个 https blog csdn net weixin 41195886 article details 127841630 解决建议都尝试一下 在user和password后边加个 0 老版本 未测试
  • O - Muddy roads

    Farmer John has a problem the dirt road from his farm to town has suffered in the recent rainstorms and now contains 1 l
  • centos7上搭建http服务器以及设置目录访问

    步骤 安装httpd服务 sudo yum install httpd Apache 的所有配置文件都位于 etc httpd conf 和 etc httpd conf d 网站的数据默认位于 var www 但如果你愿意 你可以改变它
  • HiveQL语法

    Hive SQL与标准SQL存在一些差异 但也是大同小异 HQL的基本语法为 中内容是可选的 中内容是必选的 表示内容二选一 全大写单词为关键字 建表语法 CREATE EXTERNAL TABLE IF NOT EXISTS table
  • 单片机实验(九)时钟0工作方式1中断法控制数码管0-59变化

    1 实验环境 win732位系统 keil2 proteus7 5sp3 2 实验目的 学习通过编程时钟0工作方式1中断法控制数码管0 59变化 3 实验连接图 4 实验代码 include
  • 用了Stream,代码丑爆了!姿势不对,别喷!

    程序员的成长之路 互联网 程序员 技术 资料共享 关注 阅读本文大概需要 20 分钟 来自 blog csdn net mu wind article details 109516995 Java8 的 Stream 流 加上 Lambda
  • C++11之显式转换操作符-explicit

    系列文章 C 11之正则表达式 regex match regex search regex replace C 11之线程库 Thread Mutex atomic lock guard 同步 C 11之智能指针 unique ptr s