explicit 的作用(如何避免编译器进行隐式类型转换)

news2024/11/15 20:25:04

目录

1. 隐式转换(Implicit Conversion)

2. 显式转换(Explicit Conversion)

3. 隐式转换的风险与显式转换的必要性

4. 隐式类型转换的例子

5. explicit 的作用

6. explicit 在构造函数中的作用

7. explicit 适用于转换操作符


  • 隐式类型转换 发生在类的单参数构造函数和类型转换操作符被自动调用的情况下。
  • explicit 的作用:阻止编译器进行隐式类型转换,要求调用者显式地进行类型转换或对象创建。
  • 使用场景:在类的单参数构造函数和类型转换操作符中,当隐式转换可能引发错误或误解时,使用 explicit 关键字可以提高代码的可读性和安全性。

在说明explicit 的作用之前,我们先来搞清楚什么是隐式转换,什么是显示转换。

隐式转换显式转换是两种类型转换方式,它们用于将一种类型的值转换为另一种类型。在编程语言中(如 C++、Java、Python 等),这两者的区别主要体现在转换的自动性控制权上。

explicit 是 C++ 中的关键字,用于防止编译器在某些情况下进行隐式类型转换,尤其是在构造函数和类型转换操作符中。它可以显式声明构造函数或类型转换,避免潜在的意外行为,从而提高代码的安全性和可读性。

1. 隐式转换(Implicit Conversion)

隐式转换是由编译器自动执行的类型转换。通常,当需要将一个类型的值转换为兼容的另一种类型时,编译器会隐式地进行这种转换。它不需要显式的操作或用户的干预。

特点:

  • 自动执行:不需要程序员明确地进行转换,编译器在适当的时候自动完成。
  • 安全性:隐式转换通常在转换不会丢失数据或引起精度问题时发生。
  • 简化代码:减少了类型转换的显式操作,使代码更加简洁。

常见的隐式转换:

  • 整数到浮点数的转换。
  • 窄类型到宽类型的转换,例如 intdouble
  • 从派生类到基类的转换(向上转型)。

C++ 示例:

int a = 10;
double b = a;  // 隐式转换:int 转换为 double

在这个例子中,a 被隐式地转换为 double 类型赋值给 b

Python 示例:

a = 10
b = a + 1.5  # 隐式转换:int 转换为 float

a 在进行加法操作时,自动转换为 float 类型。

2. 显式转换(Explicit Conversion)

显式转换是由程序员手动指定的类型转换方式。程序员必须通过特定的语法,明确告诉编译器执行转换操作。这种转换通常用于转换不兼容的类型,或者当隐式转换可能会导致数据丢失时。

特点:

  • 需要手动指定:程序员必须使用明确的语法进行类型转换。
  • 安全性控制:显式转换通常用于需要精确控制转换过程,避免潜在的错误或数据丢失。
  • 灵活性:可以进行更复杂和不安全的类型转换。

常见的显式转换方式:

  • C++ 中的类型转换操作:如 static_castdynamic_castreinterpret_cast
  • C 风格的类型转换:如 (int)(double)
  • Python 中的强制类型转换:如 int()float()str()

C++ 示例:

double x = 9.7;
int y = static_cast<int>(x);  // 显式转换:double 转换为 int,截断小数部分

Python 示例:

x = 9.7
y = int(x)  # 显式转换:float 转换为 int,截断小数部分

在这两个示例中,x 被显式转换为 int,而转换后的小数部分会被舍弃。

隐式转换 vs 显式转换

3. 隐式转换的风险与显式转换的必要性

隐式转换虽然方便,但有时会引发意外的错误,特别是当类型不完全兼容时,可能会导致数据丢失或精度问题。这时候,显式转换就非常有用,可以确保程序员明确意识到可能的风险并加以控制。

风险示例:

double d = 9.99;
int i = d;  // 隐式转换,数据丢失,i 变成 9

这种情况下,小数部分被丢失。如果我们希望精确控制这种行为,应该使用显式转换:

int i = static_cast<int>(d);  // 显式转换,确保数据截断是程序员预期的行为

接下来我们再来说明explicit 的作用。

4. 隐式类型转换的例子

当一个类有一个带单参数的构造函数时,编译器会自动进行隐式类型转换,将参数类型转换为该类的对象。这种隐式转换有时会导致意想不到的结果。

示例:

#include <iostream>

class MyClass {
public:
    // 构造函数,可以接受 int 类型
    MyClass(int x) {
        std::cout << "MyClass constructor called with " << x << std::endl;
    }
};

void printObject(const MyClass& obj) {
    std::cout << "Object received" << std::endl;
}

int main() {
    MyClass obj = 42;  // 隐式转换:int 转换为 MyClass 对象
    printObject(42);   // 隐式转换:int 被转换为 MyClass 对象
}

在上面的代码中:

  • MyClass obj = 42; 触发了隐式类型转换,编译器将 42 转换为 MyClass 对象。
  • printObject(42); 也触发了隐式类型转换,将 42 转换为 MyClass 对象。

虽然这种隐式转换看似方便,但在某些情况下可能会导致难以发现的错误或非预期的行为。

5. explicit 的作用

为防止不必要的隐式转换,可以在构造函数前加上 explicit 关键字。explicit 使得构造函数不能被隐式调用,只能通过显式地传递参数来调用。

示例:

#include <iostream>

class MyClass {
public:
    // 使用 explicit 防止隐式类型转换
    explicit MyClass(int x) {
        std::cout << "MyClass constructor called with " << x << std::endl;
    }
};

void printObject(const MyClass& obj) {
    std::cout << "Object received" << std::endl;
}

int main() {
    // MyClass obj = 42;  // 错误!不能进行隐式类型转换
    MyClass obj(42);     // 必须显式调用构造函数
    // printObject(42);   // 错误!需要显式转换
    printObject(MyClass(42));  // 必须显式地转换为 MyClass 对象
}

在此例中,由于使用了 explicit,编译器不再允许隐式类型转换,必须通过显式地构造对象来使用 MyClass

6. explicit 在构造函数中的作用

  • 隐式转换:当一个类有一个带单参数的构造函数时,可以通过传递该类型的参数直接创建对象,而无需显式调用构造函数,这称为隐式类型转换。
  • 使用 explicit:为构造函数添加 explicit 关键字可以阻止编译器执行隐式类型转换,要求调用者显式地进行类型转换。

代码对比:

  • 没有 explicit

class MyClass {
public:
    MyClass(int x) {
        // 构造函数
    }
};

MyClass obj = 10;  // 隐式转换
  • 没有 explicit

class MyClass {
public:
    explicit MyClass(int x) {
        // 构造函数
    }
};

MyClass obj(10);  // 显式调用

7. explicit 适用于转换操作符

除了构造函数外,explicit 也可以用于类型转换操作符,防止不合适的自动类型转换。

示例:

#include <iostream>

class MyClass {
public:
    explicit operator int() const {
        return 42;
    }
};

int main() {
    MyClass obj;
    // int x = obj;  // 错误!explicit 禁止隐式转换
    int x = static_cast<int>(obj);  // 正确,必须显式转换
    std::cout << x << std::endl;  // 输出 42
}

此例中,operator int() 被声明为 explicit,因此不能隐式转换为 int,但可以通过 static_cast 显式转换。

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

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

相关文章

常见网络层(卷积、池化、全连接)与其计算

卷积可视化&#xff1a;卷积神经网络 (CNN) 基本原理和公式_cnn公式-CSDN博客 嵌入大小计算规则【注意评论区全连接层计算规则勘误&#xff1a;Pv Wv Bv】 Conv、MaxPool、FC 池化操作和conv在kernels上计算不一致&#xff0c;在图像尺寸上的规则都是一样的。 公式可以理解…

解决windows远程桌面连接报错:这可能由于GredSSP加密数据库修正

这种问题需要修改一些远程端的安全级别 1.使用快捷键winr打开运行窗口 ------- 输入‘gpedit.msc’ 2.依次展开“计算机配置”->“管理模板”->“系统”->“凭据分配”设置名称&#xff1a; 加密数据库修正 3.双击“加密数据库修正”&#xff0c;将状态改为“启用”&a…

LDRA Testbed(TBrun)软件单元测试_实例讲解(对多次调用的函数打桩)

系列文章目录 LDRA Testbed软件静态分析_操作指南 LDRA Testbed软件静态分析_自动提取静态分析数据生成文档 LDRA Testbed软件静态分析_Jenkins持续集成&#xff08;自动静态分析并用邮件自动发送分析结果&#xff09; LDRA Testbed软件静态分析_软件质量度量 LDRA Testbed软件…

YOLOv10改进:CA注意力机制【注意力系列篇】(附详细的修改步骤,以及代码,目标检测效果优于SE和CBAM注意力)

YOLOv10改进&#xff1a;CA注意力机制【注意力系列篇】&#xff08;附详细的修改步骤&#xff0c;以及代码&#xff09; 如果实验环境尚未搭建成功&#xff0c;可以参考这篇文章 ->【YOLOv10超详细环境搭建以及模型训练&#xff08;GPU版本&#xff09;】 文章链接为&…

电脑pe是什么意思_电脑pe系统作用详细分析

有些小白很好奇&#xff0c;电脑pe是什么意思?所谓的电脑pe系统其实就是当我们的电脑出现问题而不能进入正常系统时候的一种“紧急备用”系统。如果需要重装操作系统的话&#xff0c;以往采用光盘使用的比较多&#xff0c;随着技术的进步&#xff0c;用u盘制作一个pe启动盘去安…

Kubernetes 系列 | k8s入门运维

目录 一、K8S集群搭建1.1 部署方式1.2 了解kubeadm1.3 部署流程1.3.1 初始化配置1.3.2 安装容器运行时1.3.3 安装K8S软件包1.3.4 创建集群 二、集群高可用1.1 集群高可用-堆叠1.2 集群高可用-集群外etcd 三、Pod运维3.1 Pod运维3.2 Pod的生命周期3.3 Pod状况3.4 Pod阶段3.5 容器…

【C++前缀和】3212. 统计 X 和 Y 频数相等的子矩阵数量|1672

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode3212. 统计 X 和 Y 频数相等的子矩阵数量 难度分&#xff1a;1672 给你一个二维字符矩阵 grid&#xff0c;其中 grid[i][j] 可能是 ‘X’、‘Y’ 或 ‘.’&a…

中秋佳节,科技好礼献团圆!五款数码好物大推荐

中秋节的到来&#xff0c;总是让人充满了对团圆和美好生活的向往。在这个家人团聚、朋友欢聚的美好时刻&#xff0c;除了享受月饼和团圆饭&#xff0c;还可以通过一些先进的数码好物&#xff0c;提升节日的愉悦感和生活的舒适度。从提升运动体验的南卡Runner Pro5&#xff0c;到…

Windows系统 安装 Nacos

使用说明&#xff1a;安装 Nacos 服务端&#xff0c;以单机模式启动&#xff0c;不用集群。 一、下载Nacos Nacos Server 下载 | Nacos 官网 下载解压后&#xff1a; bin&#xff1a;启动脚本&#xff1b;conf&#xff1a;配置文件 这个文件可以修改端口、增加数据库连接等配…

从零到一:为未上架APP开通微信商户支付服务的步骤详解

随着移动支付的普及&#xff0c;微信商户支付已成为众多商家不可或缺的一部分。然而&#xff0c;对于某些仍处于开发阶段或特殊需求下的APP来说&#xff0c;它们可能尚未在应用商店上架&#xff0c;但仍需接入微信支付功能以满足用户需求。本文将为您提供一份详细的微信商户支付…

2024年印尼金融科技报告解读(1) | 印尼金融科技发展现状与挑战

概述 金融科技的创新正加速全球金融普及和经济增长&#xff0c;尤其在东南亚&#xff0c;其影响尤为显著。 印尼作为该区域的经济龙头&#xff0c;凭借其庞大的人口基数和独特的地理位置&#xff0c;对"非接触式"服务和中小企业融资的需求迅猛增长&#xff0c;成为数…

mp3和mp4区别是什么?音视频转换,用这2个工具就够了

在刷视频的时候&#xff0c;在看电影的时候&#xff0c;在听歌的时候……我们经常能听到“mp3”、“mp4”这两种格式的名字。它们是什么格式&#xff1f;mp3和mp4区别是什么&#xff1f;我们能做什么&#xff1f; mp3是一种流行的音频编码格式&#xff0c;以其高效的压缩算法著…

屏幕空间UV 警戒线

屏幕空间UV 警戒线 屏幕UV已经抗锯齿

ueditor抓取图片

在ueditor.all.js文件中 修改catchremoteimage方法 原来的: 修改后: function catchremoteimage(imgs, callbacks) { //创建一个请求var oReq = new XMLHttpRequest() //获取请求地址前缀,根据自身项目获取const baseURL = http://uat.********* //url为请求地址根路径+具…

openGauss 数据库管理工具:DataKit 6.0 部署与配置实战

目录 一、DataKit简述 二、部署概要 三、系统规划 四、软件环境准备 1、关闭防火墙 2、配置时间同步 3、禁用 SELinux 4、关闭RemoveIPC 5、字符集设置 6、安装依赖包 五、openGauss DataKit部署与配置 1、openGauss 安装与配置 1.openGauss参数配置 2.重启 open…

React Native 0.76,New Architecture 将成为默认模式,全新的 RN 来了

关于 React Native 的 New Architecture 概念&#xff0c;最早应该是从 2018 年 RN 团队决定重写大量底层实现开始&#xff0c;因为那时候 React Native 面临各种结构问题和性能瓶颈&#xff0c;最终迫使 RN 团队开始进行重构。 而从 React Native 0.68 开始&#xff0c;New A…

第三次去银行办事,核心是犯了抓不住重点这个毛病

手机银行不小心输错了两次密码&#xff0c;然后就限制了交易&#xff0c;只能在柜台操作。 由此引发了比如提示密码错误、定期转活期、转账等功能的异常。 前两次去银行&#xff0c;竟然只是去解决了这些附带问题。 核心问题是限制非柜面交易啊。 哎 这就是抓不住重点&…

数据结构-堆-详解

数据结构-堆-详解 1.性质大根堆小根堆 2.实现2.1struct Heap、HeapInit、HeapDestroy2.2HeapPushAdjustUp 2.3HeapPopAdjustDown 2.4HeapTop、HeapSize、HeapEmpty 3.应用3.1堆排建堆排序 3.2TopK问题 1.性质 堆是一种特殊的完全二叉树&#xff0c;其父节点总是不大于/不小于 …

手把手教你使用亚马逊云服务器创建EC2实例

陈老老老板&#x1f934; &#x1f9d9;‍♂️本文专栏&#xff1a;生活&#xff08;主要讲一下自己生活相关的内容&#xff09;生活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f9d9;‍♂️本文简述&#xff1a;如何使用亚马逊云服务器创建EC2实例。 &#x1f9d9;‍♂…

CGAL 概念模型及Traits 概述

CGAL 概念模型及Traits 本节释了概念Concepts 、模型Models以及Traits类的含义。 CGAL Concepts and Models 概念Concepts是对类型的一组要求&#xff0c;即它具有特定的嵌套类型、特定的成员函数或具有特定的以该类型为参数的自由函数。概念的模型 Models是一个满足概念需求…