展开

  • explicit关键字的作用
  • 使用情况
    • 类型转换函数
    • 单操作数构造函数
    • 同时出现拷贝构造函数和类型转换函数
    • 拷贝构造函数
  • 总结
  • 参考文献

explicit关键字的作用
explicit关键字在写程序时使用的次数较少,但是仔细观察会发现,在C++标准库中的相关类声明中explicit出现的频率是很高的,那么explicit关键字到底有什么作用呢?接下来我就为大家一一解答.
explicit为清晰的;明确的之意.顾名思义,关键字explicit可以阻止隐式转换的发生.
例如: C++中只带有一个参数的构造函数,或者或者除了第一个参数外其余参数都有缺省值的多参构造函数,承担了两个角色:
1.用于构建单参数的类对象.
2.隐含的类型转换操作符.

例如:一个类A的构造函数A(int i)就是,既可以用来作为构造器,又可以实现隐式转换A a=1;因为1可以通过构造函数A(int i)转换为一个类A的对象。(隐含的类型转换操作符)
但有时我们并不想让他进行隐式类型转换,这时C++的explicit关键字就起到作用了.

注意:当类的声明和定义分别在两个文件中时,explicit只能写在在声明中,不能写在定义中。
下面我将为大家介绍三种使用explicit关键字的情况:使用情况
类型转换函数

#include<iostream>
using namespace std;
class Fraction{
public:Fraction(int numerator, int denominator = 1): m_numerator(numerator), m_denominator(denominator){}operator double() const{return (double)m_numerator/m_denominator;}
private:int m_numerator;int m_denominator;
}int main(void)
{Fraction fraction(3, 5);double d = 3.5 + f;cout << d << endl;return 0;
}

我们设计了一个Fraction类(分数类), 在主函数中定义了一个分数对象f,然后将3.5 + f赋值给double类型变量d, 但是我们发现f并不是一个double类型的变量,因此编译器会从Fraction类中寻找operator double()函数,隐式调用该函数将Fraction类型转换成一个double类型. operator double()就是我们所说的类型转换函数(type conversion function).

类型转换函数的一般形式

operator 数据类型 const()
{
//函数实现
}

1.转换函数必须是类的成员函数
2.转换函数不能声明返回类型
3.形参列表必须为空
4.类型转换函数通常应该是const

当我们想要在明确声明类型转换的时候,才使用类型转化函数时,这时我们就需要使用到explicit关键字了.使用方法如下:

#include<iostream>
using namespace std;
class Fraction{
public:Fraction(int numerator, int denominator = 1): m_numerator(numerator), m_denominator(denominator){}explicit operator double() const{return (double)m_numerator/m_denominator;}
private:int m_numerator;int m_denominator;
}int main(void)
{Fraction fraction(3, 5);double d = 3.5 + static_cast<double>(f);cout << d << endl;return 0;
}

注意,这时当我们想调用类型转换函数的时候,需要写成static_cast<double>(f);

注意static_cast 是C++11 引入的类型转换运算符.

单操作数构造函数
还是采用上面的Fraction类,这次我们重载(overload) “+” 号运算符,使得仍然可以达到相同的效果.

#include<iostream>
using namespace std
class Fraction
{public:Fraction(int numerator, int denominator = 1): m_numerator(numerator), m_denominator(denominator){}double operator+(const Fraction& a){return (a.m_numerator + this->m_numerator)/(a.denominator + this->m_denominator);}private:int m_numerator;int m_denominator;}int main(void)
{Fraction fraction(3, 5);double d = f + 3;cout << d << endl;return 0;
}

在double d = f + 3 这句话中构造函数就是前面所提到的第二种角色隐含的类型转换操作符.,因为执行到这句话首先会调用+的重载函数,该函数的调用对象默认为左操作数,右操作数为Fraction类型,因此会调用构造函数将3转换成Fraction类型,然后将得到的返回值double类型赋值给变量d.
同理如果不想让构造函数进行隐式类型转换,可以在构造函数前面加上explicit关键字,防止进行隐式转换.使用方法如下:

#include<iostream>
using namespace std
class Fraction
{public:explicit Fraction(int numerator, int denominator = 1): m_numerator(numerator), m_denominator(denominator){}double operator+(const Fraction& a){return (a.m_numerator + this->m_numerator)/(a.denominator + this->m_denominator);}private:int m_numerator;int m_denominator;}int main(void)
{Fraction fraction(3, 5);double d = f + 3;cout << d << endl;return 0;
}

你可能会注意到,加上explicit 关键字之后,这个代码将不能正确执行.

同时出现拷贝构造函数和类型转换函数
我们看如下一段代码:

#include<iostream>
using namespace std
class Fraction
{public:Fraction(int numerator, int denominator = 1): m_numerator(numerator), m_denominator(denominator){}operator int(){return m_numerator/denominator;}int operator+(const Fraction& a){return (a.m_numerator + this->m_numerator)/(a.denominator + this->m_denominator);}private:int m_numerator;int m_denominator;}int main(void)
{Fraction fraction(3, 5);int d = f + 3;cout << d << endl;return 0;
}

这时你会发现会产生一个二义性问题,在执行int d = f + 3的时候到底是该选择类型转换函数,将f转换成int类型再继续运算呢?还是应该将3作为构造函数的参数进行隐式转换,然后再调用+运算符重载函数呢?
解决这个问题的办法就是使用explicit关键字限制,具体方法有两种你:
1.在构造函数前面加上explicit关键字, 防止int类型隐式转换成为Fraction类型.
2.在类型转换函数前面加上explicit关键字,这样只有显示调用类型转换static_cast<int>(f)时,才会调用该函数.

拷贝构造函数
Copy constructor也是同样的,如果Copy constructor被声明为explicit,则这个类对象不能隐式调用,用于传参传递和函数返回值.

//隐式调用
Complex<double> v1(1.2, 2.3);
Complex<double> v2 = v1;        // 编译错误 C2558  //参数按值传递
void func(Complex<double> v);
func(v1);                       // 编译错误 C2664  //返回值按值传递
Complex<double> func()
{  Complex<double> v1(2.3, 1.2);  return v1;                  // 编译错误 C2558
}  

总结
C++中,一个参数的构造函数(或者除了第一个参数外其余参数都有缺省值的多参构造函数),承担了两个角色。
用于构建单参数的类对象
隐含的类型转换操作符
explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了
声明为explicit的构造函数不能在隐式转换中使用,只能显示调用,去构造一个类对象。
Base base(‘a’) //显示调用,OK
Base base = ‘a’ //隐是调用,err

尽量避免有二义性的类型转换,如果类中包含一个或多个隐式类型转换,则必需使用explicit关键字确保在类类型和目标类型之间只存在唯一一种隐式转换方式,否则将出现二义性。
但是将拷贝构造函数声明成explicit并不是良好的设计,一般只将有单个参数的constructor声明为explicit,而copy constructor不要声明为explicit.
参考文献
本文主要参考了如下三个文章,对其进行了总结

  1. C++ 类型转换函数 与 explicit
  2. C++学习之explicit关键字详解
  3. C++ explicit关键字详解
  4. C++ 对象构造, 拷贝, 赋值和隐式类型转换总结

————————————————
版权声明:本文为CSDN博主「code_campaign」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/l2563898960/article/details/97769569

C++ 中explicit关键字详解相关推荐

  1. C++ explicit关键字详解(用于构造函数)

    C++ explicit关键字详解(用于构造函数) C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生.声明为explicit的构造函数不能在隐式转换中使用. ...

  2. explicit关键字详解

    C++ explicit关键字详解 首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是impl ...

  3. java中new关键字详解

    java中new关键字详解 在java中我们可以经常使用new来创建一个对象,但是这对于初学者来说可能只会使用却不能理解new关键字和它的语法 new关键字的语法 注意使用前先导包,一般我们使用ide ...

  4. Java中super关键字详解

    Java中super关键字详解 super有什么用? super什么时候不可以省略呢? super在内存图中是如何存在的呢? super使用时的注意事项 super有什么用? (1)当子类中构造方法第 ...

  5. 在 C/C++中 static 关键字详解

    static 关键字详解 C/C++ 中的 static 1. 静态局部变量 2. 静态全局变量 全局变量 与 extren 3. static 修饰函数 C++的 static 成员 静态成员变量 ...

  6. JS中this关键字详解

    本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...

  7. C++ explicit关键字详解(转载)

    转载:https://www.cnblogs.com/ymy124/p/3632634.html 首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函 ...

  8. explicit关键字详解(C++ )

    一:首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造 ...

  9. C explicit 关键字详解

    explicit关键字的作用 explicit关键字在写程序时使用的次数较少,但是仔细观察会发现,在C 标准库中的相关类声明中explicit出现的频率是很高的,那么explicit关键字到底有什么作 ...

最新文章

  1. 卷积神经网络初步认知
  2. lable标签的用途
  3. java 增量编译_java增量/全量编译接口应用
  4. linux基础命令 sed
  5. 【联盛德W806上手笔记】五、TIM定时器
  6. GCC Inline ASM GCC内联汇编
  7. 东京食尸鬼 第四季 高清下载
  8. 可重复使用的外科缝合器行业调研报告 - 市场现状分析与发展前景预测
  9. monggodb和MySQL同步问题_monggoDB添加到windows服务
  10. 计算机一级等级软件未来教育 手机版,计算机一级模拟考试软件手机版
  11. 解决Linux下redis客户端工具连接不到redis服务
  12. ER Studio 使用笔记
  13. MATLAB中四阶单位矩阵,matlab-线性代数 创建 N阶数量矩阵 N阶单位矩阵 对角矩阵 范德蒙矩阵 等差数列......
  14. Rayman的绝顶之路——Leetcode每日一题打卡12
  15. typedef定义结构体数组类型
  16. blos硬盘启动台式计算机,戴尔台式机bios设置硬盘启动教程--系统之家
  17. 计算机主机发出滴滴声音怎么办,电脑蓝屏后主机滴滴的响应该怎么处理教程
  18. 错误Illegal invocation;使用jquery的ajax上传文件报错Illegal invocation
  19. android siri声波动画,Waver声波效果开源项目:和 Siri 一起学数学
  20. 微信小程序语音转文字demo

热门文章

  1. Windows 7 改变文本区或文本框的颜色
  2. 弱电转网络工程师可行吗?过来人分享转行成功经验及路线
  3. spyder pyecharts不显示_专业显示器凭什么比家用显示器贵?优派VP2785-2K:贵是有原因的...
  4. 波兰科研人员提出可准确区分活人与死人的虹膜识别技术
  5. 传智健康——七牛云技术用于图片存储
  6. Smarty教程[1]
  7. android相册加密如何实现,vivo手机如何给相册加密?vivo手机相册加密教程
  8. 高DPI显示---High DPI Displays
  9. mplayer-php,mplayer ww编译版-简单但极其优秀的播放器
  10. WIN10系统改装WIN7系统