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 的相关文章

随机推荐

  • 维金细说“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