深入理解C++中的explicit关键字

深入理解C++中的explicit关键字

kezunhai@gmail.com

http://blog.csdn.net/kezunhai


         C++中的explicit关键字只能用于修饰只有一个参数构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,构造函数默认情况下即声明为implicit(隐式)。

         关于explicit关键字,先看看MSDN上的解释:

        This keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object

        从上面的解释可以看到, explicit关键字的作用:禁止隐式调用类内的单参数构造函数,这主要包括如下三层意思:

         (1)该关键字只能用来修饰类内部的构造函数

         (2)禁止隐式调用拷贝构造函数

         (3)禁止类对象之间的隐式转换

           首先,来看看隐式转换,如下例:

[cpp] view plaincopy
  1. class CExplict  
  2. {  
  3. public:  
  4.     CExplict();  
  5.     CExplict( bool _explicit)  
  6.     {  
  7.         this->is_explict = _explicit;  
  8.     }  
  9.     CExplict(const CExplict& other)  
  10.     {  
  11.         this->is_explict = other.is_explict;  
  12.     }  
  13.     friend void printExplicit(const CExplict& cx);//友元函数的实现可以在类外定义,但必须在类内部声明 
  14.   
  15. private:  
  16.     bool is_explict;  
  17. };  
  18.   
  19. void printExplicit(const CExplict& cx)  
  20. {  
  21.     cout<<"is_explict="<<cx.is_explict<<endl;  
  22. }  
  23.   
  24. int main( int argc, char* argv[])  
  25. {  
  26.     CExplict cx1 = true;  
  27.     CExplict cx2 = cx1;  
  28.     printExplicit(cx1);  
  29.     printExplicit(cx2);  
  30.     printExplicit(false);  
  31.     getchar();  
  32.     return 1;  
  33. }  
      在上面的代码中:

[cpp] view plaincopy
  1. CExplict cx1 = true;  
  2. CExplict cx2 = cx1;  
  3. printExplicit(false);  
隐式调用CExplict类的单参数构造函数。这种调用在C++语法中是允许的,但是诸如:CExplict cx1 = true和printExplicit(false)这种表达形式看着很别扭,也很让人费解,将一个bool型的值赋给一个CExplicit类的cx1,使代码的可读性变差。

          因此,为了禁止对类的单参数构造函数的隐式调用,C++引入了关键字explicit。在类的定义中,在任何一个单参数构造函数钱加explicit关键字,就可以禁止对该构造函数的隐式调用。如下:

[cpp] view plaincopy
  1. class CExplict  
  2. {  
  3. public:  
  4.     CExplict();  
  5.     explicit CExplict( bool _explicit)  
  6.     {  
  7.         this->is_explict = _explicit;  
  8.     }  
  9.     CExplict(const CExplict& other)  
  10.     {  
  11.         this->is_explict = other.is_explict;  
  12.     }  
  13.     friend void printExplicit(const CExplict& cx);    
  14.   
  15. private:  
  16.     bool is_explict;  
  17. };  
  18.   
  19. void printExplicit(const CExplict& cx)  
  20. {  
  21.     cout<<"is_explict="<<cx.is_explict<<endl;  
  22. }  
  23.   
  24. int main( int argc, char* argv[])  
  25. {  
  26.     CExplict cx1 = true;  
  27.     CExplict cx2 = cx1;  
  28.     printExplicit(cx1);  
  29.     printExplicit(cx2);  
  30.     printExplicit(false);  
  31.     getchar();  
  32.     return 1;  
  33. }  
此时,在调用上面一段代码,则会报:  error C2440: “初始化”: 无法从“bool”转换为“CExplict”的错误,为了使程序能正确运行,需要将main函数内的代码改为:

[cpp] view plaincopy
  1. int main( int argc, char* argv[])  
  2. {  
  3.     CExplict cx1(true);  
  4.     CExplict cx2(cx1);  
  5.     printExplicit(cx1);  
  6.     printExplicit(cx2);  
  7.     printExplicit(CExplict(false));  
  8.     getchar();  
  9.     return 1;     
  10. }  

至此,程序就可以正常运行,而且进一步增加了程序的可读性。

         总结:

        (1)explicit关键字只需用于类内的单参数构造函数前面。由于无参数的构造函数和多参数的构造函数总是显示调用,这种情况在构造函数前加explicit无意义。

        (2)如果想禁止类A对象被隐式转换为类B对象,可在类B中使用关键字explicit,即定义这样的转换构造函数

[cpp] view plaincopy
  1.        explicit B(A a)  
  2. {  
  3.   
  4. }  
  5. explicit B(const A &a)  
  6. {  
  7.   
  8. }  
        google的c++规范中提到explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit。例如作为其他类的透明包装器的类。
  effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit,鼓励大家遵循相同的政策。

作者:kezunhai出处:http://blog.csdn.net/kezunhai欢迎转载或分享,但请务必声明文章出处。

from:https://blog.csdn.net/kezunhai/article/details/38417087

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

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

相关文章

JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结(转)

hibernate以及mybatis都有过学习&#xff0c;在java面试中也被提及问道过&#xff0c;在项目实践中也应用过&#xff0c;现在对hibernate和mybatis做一下对比&#xff0c;便于大家更好的理解和学习&#xff0c;使自己在做项目中更加得心应手。 第一方面&#xff1a;开发速度的对…

Caffe源码解析4: Data_layer

转载请注明出处&#xff0c;楼燚(y)航的blog&#xff0c;http://home.cnblogs.com/louyihang-loves-baiyan/ data_layer应该是网络的最底层&#xff0c;主要是将数据送给blob进入到net中&#xff0c;在data_layer中存在多个跟data_layer相关的类 BaseDataLayerBasePrefetchingD…

理解C++中拷贝构造函数

拷贝构造函数的功能是用一个已有的对象来初始化一个被创建的同样对象&#xff0c;是一种特殊的构造函数&#xff0c;具有一般构造函数的所有特性&#xff0c;当创建一个新对象的时候系统会自动调用它&#xff1b;其形参是本类对象的引用&#xff0c;它的特殊功能是将参数代表的…

IDEA mybatis-generator-maven-plugin 插件的使用

2019独角兽企业重金招聘Python工程师标准>>> pom.xml中添加插件 <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version><configuratio…

python优秀网友学习笔记推荐

AstralWindMr.Seven 转载于:https://www.cnblogs.com/migongci0412/p/5154892.html

深入理解CRITICAL_SECTION

摘要临界区是一种防止多个线程同时执行一个特定代码节的机制&#xff0c;这一主题并没有引起太多关注&#xff0c;因而人们未能对其深刻理解。在需要跟踪代码中的多线程处理的性能时&#xff0c;对 Windows 中临界区的深刻理解非常有用。本文深入研究临界区的原理&#xff0c;以…

webpack进阶之插件篇

上一篇博客讲解了webpack环境的基本&#xff0c;这一篇讲解一些更深入的内容和开发技巧。基本环境搭建就不展开讲了 一、插件篇 1. 自动补全css3前缀 autoprefixer 官方是这样说的&#xff1a;Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use…

QT:QObject 简单介绍

QObject 是所有Qt对象的基类。QObject 是Qt模块的核心。它的最主要特征是关于对象间无缝通信的机制&#xff1a;信号与槽。 使用connect()建立信号到槽的连接&#xff0c;使用disconnect()销毁连接&#xff0c;使用blockSignals()暂时阻塞信号以避免无限通知循环&#xff0c;使…

利用malloc定义数组

使用malloc方法时&#xff0c;应导入文件 #include<malloc.h> 1.利用malloc定义一维数组 int *num (int *)malloc(sizeof(int)*8); // 定义一个一维数组有8个元素&#xff0c;等价于 int num[8]; 2.利用malloc定义二维数组 int **num &#xff08; int **&#xff09…

C++中基类的析构函数为什么要用virtual虚析构函数

from&#xff1a;https://blog.csdn.net/iicy266/article/details/11906457知识背景要弄明白这个问题&#xff0c;首先要了解下C中的动态绑定。 关于动态绑定的讲解&#xff0c;请参阅&#xff1a; C中的动态类型与动态绑定、虚函数、多态实现 正题直接的讲&#xff0c;C中基类…

第二章 Python基本元素:数字、字符串和变量

Python有哪些内置的数据类型&#xff1a; True False #布尔型 42 100000000 #整型 3.14159 1.0e8 #浮点型 abcdes #字符串 2.1 变量、名字和对象 python中统一的形式是什么&#xff1f; 对象&#xff0c;所有的对象都是以对象的形式存在…

Mac - 设置NSButton 的背景色

- (void)drawRect:(NSRect)dirtyRect {[super drawRect:dirtyRect];[[NSColor clearColor] setFill];NSRectFill(self.bounds);self.wantsLayer YES;self.layer.cornerRadius 8;self.layer.masksToBounds YES; } 转载于:https://www.cnblogs.com/741162830qq/p/5157046.html…

C++中static关键字作用总结

from&#xff1a;https://www.cnblogs.com/songdanzju/p/7422380.html1.先来介绍它的第一条也是最重要的一条&#xff1a;隐藏。&#xff08;static函数&#xff0c;static变量均可&#xff09; 当同时编译多个文件时&#xff0c;所有未加static前缀的全局变量和函数都具有全局…

C Primer Plus 第7章 C控制语句:分支和跳转 7.4 一个统计字数的程序

2019独角兽企业重金招聘Python工程师标准>>> 首先&#xff0c;这个程序应该逐个读取字符&#xff0c;并且应该有些方法判断何时停止&#xff1b;第二&#xff0c;它应该能够识别并统计下列单位&#xff1a;字符、行和单词。下面是伪代码描述&#xff1a; read a cha…

深入理解extern用法

from&#xff1a;https://blog.csdn.net/z702143700/article/details/46805241一、 extern做变量声明 l 声明extern关键字的全局变量和函数可以使得它们能够跨文件被访问。 我们一般把所有的全局变量和全局函数的实现都放在一个*.cpp文件里面&#xff0c;然后用一个同名的*.h文…

收集整理的非常有用的PHP函数

为什么80%的码农都做不了架构师&#xff1f;>>> 1、PHP加密解密 2、PHP生成随机字符串 3、PHP获取文件扩展名&#xff08;后缀&#xff09; 4、PHP获取文件大小并格式化 5、PHP替换标签字符 6、PHP列出目录下的文件名 7、PHP获取当前页面URL 8、PHP强制下载文件 9、…

进程间的通信方式——pipe(管道)

from&#xff1a;https://blog.csdn.net/skyroben/article/details/715133851.进程间通信每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内…

bash中(),{},(()),[],[[]]的区别

前言:在bash中遇到各种括号&#xff0c;同时在进行字符数值比较判定时&#xff0c;总是不断出现问题&#xff0c;于是通过参考《advanced bash-scripting guide》&#xff0c;同时在centos 6.7版本上进行测试&#xff0c;现况总结如下。如有纰漏&#xff0c;望指正。一.()一个命…

多进程和多线程之间的通信方式及通信实现步骤小结

进程间通信方式 # 管道( pipe )&#xff1a;管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 # 有名管道 (namedpipe) &#xff1a; 有名管道也是半双工的通信方式&#xff0c;…

highcharts 显示网格

2019独角兽企业重金招聘Python工程师标准>>> xAxis: { gridLineColor: #197F07, gridLineWidth: 1 }, yAxis: { gridLineColor: #197F07, gridLineWidth: 2 }, 转载于:https://my.oschina.net/LingBlog/blog/697885