explicit关键字解析

2023-11-17

C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。
  C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。 1 是个构造器 2 是个默认且隐含的类型转换操作符。
  所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。
  这样看起来好象很酷, 很方便。 但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用,使用, 不能作为类型转换操作符被隐含的使用。 呵呵, 看来还是光明正大些比较好。
  explicit构造函数的作用
  解析:

  explicit构造函数是用来防止隐式转换的。请看下面的代码:

class Test1
{
public:
  Test1(int n) { num = n; } //普通构造函数
private:
  int num;
};
class Test2
{
public:
  explicit Test2(int n) { num = n; } //explicit(显式)构造函数
private:
  int num;
};
int main()
{
  Test1 t1 = 12; //隐式调用其构造函数, 成功
  Test2 t2 = 12; //编译错误,不能隐式调用其构造函数
  Test2 t3(12); //显示调用成功
  return 0;
}
Test1的构造函数带一个int型的参数,代码19行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码20行会出现编译错误。
  普通构造函数能够被隐式调用。而explicit构造函数只能被显示调用。
=======================================================================================
#include <iostream>
using namespace std;

struct STU
{
    int ID;
    char* name;
    float score;
};
class Student{
   Student();
    void set(STU stu);
    void disp(); 
    STU data;
};
Student::Student()
{
   STU stu = {0,"name",0.};
   data = stu;
}
void Student::set(STU stu)
{ 
    data = stu;
}
void Student::disp()
{ 
    cout<<"student ID : "<<data.ID<<endl 
        <<"student name : "<<data.name<<endl
        <<"student score: "<<data.score<<endl;
}
int main()
{ 
   STU stu = {5,"zbc",0.};
   Student student; 
   student.set(stu); 
   student.disp(); 
   return 0;
}
此时,设置的构造函数无传入参数,在main程序中通过使用set函数设置data,正确。
但是,如果将main函数改为:

int main()
{
    STU stu = {5,"zbc",0.};
    Student student = stu;
    student.disp();
    return 0;
}
报错,因为虽然我们的类中的data数据是STU类型的,但是系统无法知道怎样将STU类型的结构体数据传给Student类的student对象。
修改程序如下:

#include <iostream>
using namespace std;
struct STU
{
    int ID;
    char* name;
    float score;
};

class Student
{
public:
    Student();
    Student(STU stu);
    void set(STU stu);
    void disp();
    STU data;
};
Student::Student()
{
   STU stu = {0,"name",0.};
   data = stu;
}
Student::Student(STU stu)
{
    data = stu;
}
void Student::set(STU stu)
{
    data = stu;
}
void Student::disp()
{
    cout<<"student ID   : "<<data.ID<<endl
        <<"student name : "<<data.name<<endl
        <<"student score: "<<data.score<<endl;
}

int main()
{
    STU stu = {5,"abc",0.};
    Student student=stu;
    student.set(stu);
    student.disp();
    return 0;
}
这一次,因为Student类多了一个带参数的构造函数,并且这个参数类型正好是STU类型,那么在main函数中使用下面这一句时,无错误。
    Student student=stu;
但是,实际上讲一个数据直接赋给类,是有一定的危险性的,那怎么办呢,总不能让我删掉构造函数吧?
通过explicit关键字解决吧。
只改动一个地方,就是在类定义中的带参数构造函数声明处,在句首加上explicit关键字。此时,再次运行程序,提示出错:
error C2440: “初始化”: 无法从“STU”转换为“Student”
更有趣的事情发生在下面代码中:
#include <iostream>
using namespace std;

struct STU
{
    int ID;
    char* name;
    float score;
};

class Student
{
public:
    Student();
    Student(STU stu);
    void set(STU stu);
    void disp();
    float data;
};
Student::Student()
{
   data = 0.;
}
Student::Student(STU stu)
{
    data = stu.score;
}
void Student::set(STU stu)
{
    data = stu.score;
}
void Student::disp()
{
     cout   <<"student score: "<<data<<endl;
}

int main()
{
    STU stu = {5,"zhw",99.};
    Student student=stu;
    student.disp();
    return 0;
}
结果显示:


神奇吧?怎么说呢?就好像自动添加了带参数的构造函数后
Student student=stu;
系统就把上面一行语句认为是设置student.data = stu.score;
不明白吗?不好笑吗?好吧,那就洗洗睡吧。


参考:百度百科,http://baike.baidu.com/view/2422253.htm#2

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

explicit关键字解析 的相关文章

  • 画出有3个节点的树和有3个结点的二叉树的所有不同的形态

    画的难看了点
  • 【HDLBits 刷题 11】Circuits(7)Finite State Manchines 18-26

    目录 写在前面 Finite State Manchines Fsm serialdata Fsm serialdp Fsm hdlc Design a Mealy FSM ece241 2014 q5a ece241 2014 q5b 2
  • Data->Iopb->Parameters.Create.Options & FILE_DIRECTORY_FILE 判断是否为路径

    如何在minifilter 判断操作的文件对象是目录还是文件呢 有很多人发现答案是 Data gt Iopb gt Parameters Create Options FILE DIRECTORY FILE 是否成立 不过也有很多人发现 上
  • centos7 nginx 配置 ssl证书

    安装nginx 从阿里云服务器下载 nginx版本的ssl证书 防止再 etc nginx ssl 下 停止 nginx 服务 systemctl stop nginx 修改配置文件 etc nginx conf d root izm5ej
  • app离线消息推送服务器,在线消息推送和离线消息推送(3)

    首先介绍一下具体的功能设计 整个系统由服务端 客户端组成 客户端包含前端 浏览器端 pyqt桌面端 和后台 用于添加要推送的消息 因为浏览器端不容易注意到实时提醒 所以我将实时提醒功能放到pyqt桌面端中实现 如托盘区闪烁等醒目的方式 浏览
  • Unity 数据保存失败

    问题 游戏数据突然保存不了了 没有任何报错 切后台保存也出问题 编辑器上和PC端没问题 移动端上保存不了 原因 我使用的存储方式是 Newtonsoft Json 将对象转换成加密字符串并保存到本地 而不巧的是 我使用了 HashSet 这
  • BOOST升压电路原理详解

    原文来自公众号 工程师看海 BOOST升压电源是利用开关管开通和关断的时间比率 维持稳定输出的一种开关电源 它以小型 轻量和高效率的特点被广泛应用在各行业电子设备找那个 是不可缺少的一种电源架构 公众号后台回复 boost仿真文件 Boos
  • Linux 添加开机启动方法

    添加开启启动的方式一般有如下几种 第一种 把开机命令 写入到os的启动文件之中 伴随着启动文件的读取 顺便帮你把要启动的任务 一起启动了 第二种 把启动任务 放到os的启动目录下 os启动过程之中 会执行所有放在此目录下的任务 第三种 os
  • KaTeX数学公式输入

    序号 运算符 输入 举例 举例代码 1 x y
  • 【Java 学习】方法 和 一些编程案例

    文章目录 一 概述 二 案例 1 计算1 n的和返回 2 判断整数是奇数还是偶数 3 数组求最值改方法实现 三 方法的内存原理 四 方法参数传递机制 基本类型 引用类型 五 参数传递的案例 1 打印整型数组内容 2 从数组中查询指定元素的索
  • 【机器学习】SMO算法

    1 SMO基础概念 将原始最优化问题转化成了其对偶问题 因为对偶问题是一个凸二次规划问题 这样的凸二次规划问题具有全局最优解 其中 xi yi xi yi 表示训练样本数据 xixi为样本特征 yi 1 1 yi 1 1 为样本标签 C为惩
  • 中国货币超发严重 去年新增货币占全球近一半

    提要 2009年以来 中国已成为目前全球最大的 印钞机 2012年 全球新增货币供应量中国占近一半 21世纪网评估发现 均衡人均收入差异后 中国的经济货币化程度高居全球前列 截至2012年末 中国M2余额达到人民币97 42万亿元 居世界第
  • JS考点

    JavaScript 1 原始值和引用值类型及区别 原始值即存在栈中的数据 包含symbol number string null undefined boolean类型 引用值即存在堆中的对象 对象地址 指针 存在栈中 指向堆中存储的数据
  • 2021-07-25

    神经网络 M P神经元 感知机 感知机 神经网络 M P神经元 1 M P神经元 模拟生物行为的数学模型 接手n个输入 来自其他的神经元 并给各个输入赋予权重计算加权和 再跟自己特有的阀值 比较 通常用减法 最后经过激活函数 模拟 抑制 和
  • Stable Diffusion Base Model from safetensors transfer to diffusers

    Steps File Setup Clone the ControlNet model repo from HF into a folder like hf controlnet model git clone https huggingf
  • Qt 中父子关系使用总结

    背景 Qt 中到父子关系和类的继承无关 仅表示对象间到从属关系 继承自 QObject 的对象在构造时需要指定父对象指针 include
  • 计算机基础知识+Java语言基础 +JAVA学习笔记-DAY01

    计算机基础知识 01 01 计算机概述 了解 A 什么是计算机 计算机在生活中的应用举例 计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装

随机推荐

  • Cent OS6.5 安装nodeJS(分分钟搞定)

    第一步 下载 cd opt wget https nodejs org dist v7 5 0 node v7 5 0 linux x64 tar xz 第二步 解压缩文件包 xz d node v7 5 0 linux x64 tar x
  • hive原理与源码分析-hive源码架构与理论(一)

    什么是Hive 数据仓库 存储 查询 分析大规模数据 SQL语言 简单易用的类SQL查询语言 编程模型 允许开发者自定义UDF Transform Mapper Reducer 来更简单地完成复杂MapReduce无法完成的工作 数据格式
  • 运放增加输出电流

    功率输出模块 采用三极管9012 9013来进行双向扩流以提高其带载能力 可以完全满足发挥部分所要求的稳幅输出能力 当负载变化时 其输出电压幅度变化小于3 如图所示 集成运放的扩流和扩压 一 集成运放的扩流 在集成运放的输出端再加一级互补对
  • k8s-client(java)从6.0.1升级到11.0.0出现patch问题may not be specified for non-apply patch/cannot unmarshal...

    背景 kubernetes client java升级 复杂的patch出现各种问题 并且没有找到解决方案 经过研究 测试 找到了解决方案 希望能帮助到使用kubernetes client java客户端的同学 patch方法调用出现异常
  • IEEE 1471(ISO/IEC/IEEE 42010)架构描述方法

    ISO IEC IEEE 42010 架构描述方法 关于 背景 架构描述 利益相关者和关注点 架构视图和架构观点 架构模型 架构关系 架构原理 关于 本文对软件体系架构的描述方法的研究基于 ISO IEC IEEE 42010 ISO IE
  • unity ethan_响应式网页设计的挑战,Ethan Marcotte

    unity ethan In this episode of the Versioning Show David and Tim are joined by Ethan Marcotte a well known designer who
  • c语言设计(TVI)地铁自动售票机---@颜麓

    设计TVI 地铁自动售票机 机软件 输入站数 计算费用 计费规则 6站2元 7 10站3元 11站以上为4元 输入钱数 计算找零 找零时优先找回面额大的钞票 找零方式为各种面额张数 可识别面额 100 50 20 10 5 1 includ
  • Sentinel整合Ribbon/OpenFeign,Sentinel自定义限流熔断

    Sentinel服务熔断环境搭建 服务熔断 应对微服务雪崩效应的一种链路保护机制 类似保险丝 需要完成Sentinel整合Ribbon openFeign 所以我们先要搭建环境 那么先从整合Ribbon开始 环境搭建 为了演示操作 所以在这
  • DBeaver改成英语

    DBeaver改成英语 安装目录中有个dbeaver ini文件 追加 Duser language en可以改回英文 有些数据库术语翻译后反而不太容易理解
  • java获取唯一时间戳Id.多线程保证唯一性

    工程里有获取唯一时间戳作为id的需求 想了想用乐观锁cas实现 自旋 cas原子性操作获得了绝对唯一的时间戳 系统时间 纳秒版本 单机有效 不能分布式调用 public class AtomicTimeStamp private Atomi
  • Anaconda的安装与环境配置

    这里简单的记录一下Anaconda的安装过程 没有干货 只是记录 但也看了就会 下载安装包 这里有两个下载地址 分别是官网和清华镜像源 推荐清华镜像 下的快 官网下半天还可能失败 无论是哪个下载地址 找到对应你系统的安装程序下载即可 官网
  • Ubuntu下安装JDK图文教程详解

    操作系统 Ubuntu 11 10 我们选择的是jdk1 6 0 30版本 安装文件名为jdk 6u30 linux i586 bin 1 复制jdk到安装目录 1 假设jdk安装文件在桌面 我们指定的安装目录是 usr local jav
  • 可以编辑的table antd

    版本一 效果图 有保存按钮 antd3 代码 import React Component from react import Form Input Button Table Divider Popconfirm Tooltip from
  • 19_复制目录下所有文件夹和目录CopyFile()

    复制目录下所有文件夹和目录CopyFile 想一下 若要复制文件夹 可以在目录位置新建一个文件夹 然后将源文件夹中里面的文件进行遍历 一个一个的复制到目标文件夹中即可 void EnumCopyFile 输入参数 TCHAR szSrcRo
  • STL——vector以及emplace_back分析

    1 这里需要注意凡是连续空间的容器都提供operator 是为了数组操作 2 back 应该是 end 1 3 vector的大小为12 vector的迭代器为指针 1 emplace back 1 相比push back 如果传入临时对象
  • matlab中的锐度测量,锐度(解析度)MTF定义及测试

    Image sharpness 图像锐度 解析度 锐度无疑是最重要的摄影图像质量的评价因素 它是关系到图片中有多少细节可以被辨认的最密切因素 但它不是唯一的重要因素 其他重要因素包括色差 与锐度密切相关 噪音 动态范围 与噪声密切相关 和色
  • mysql常用命令

    mysql命令 查询 限制返回个数及偏移量 m 偏移量 n 个数 只限制个数可省略m 如limit 2 select from
  • IntelliJ IDEA破解

    今天写个IDEA破解 废话不多说 直接给网址 官网 https www jetbrains com idea 破解注册码 http idea lanyus com 里面有永久破解 还有注册码 可你根据你的喜爱 来选择 今天写一下它的破解补丁
  • HashMap之扩容原理

    一 什么是HashMap HashMap 数据结构为 数组 链表 JDk1 7 JDK1 8中增加了红黑树 其中 链表的节点存储的是一个 Entry 对象 每个Entry 对象存储四个属性 hash key value next 二 为什么
  • explicit关键字解析

    C 提供了关键字explicit 可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生 声明为explicit的构造函数不能在隐式转换中使用 C 中 一个参数的构造函数 或者除了第一个参数外其余参数都有默认值的多参构造函数 承担了两个角