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)禁止类对象之间的隐式转换

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

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. class CExplict
  6. {
  7. public:
  8. CExplict( bool _explicit)
  9. {
  10. this->is_explict = _explicit;
  11. }
  12.  
  13. CExplict(const CExplict& other)
  14. {
  15. this->is_explict = other.is_explict;
  16. }
  17.  
  18. friend void printExplicit(const CExplict& cx);
  19.  
  20. private:
  21. bool is_explict;
  22. };
  23.  
  24. void printExplicit(const CExplict& cx)
  25. {
  26. cout<<"is_explict="<<cx.is_explict<<endl;
  27. }
  28.  
  29. int main( int argc, char* argv[])
  30. {
  31. CExplict cx1{};
  32. CExplict cx2{3.14};
  33. CExplict cx3 = false;
  34. printExplicit(cx1);
  35. printExplicit(cx2);
  36. printExplicit(cx3);
  37. printExplicit(false);
  38. printExplicit(3.14);
  39. return ;
  40. }

奇怪吗?但是程序可以正常执行,隐式调用CExplict类的单参数构造函数,这种调用在C++语法中是允许的。编译器首先会以true构造一个临时对象,在将此临时对象通过赋值构造函数赋值给cx1。但是诸如:CExplict cx1{1}和printExplicit(false)这种表达形式看着很别扭,也很让人费解,将一个bool型的值赋给一个CExplicit类的cx1,使代码的可读性变差。

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

在CExplict构造函数前添加explicit,在执行上面一段代码,则会报:

error C2440: “初始化”: 无法从“bool”转换为“CExplict”的错误,为了使程序能正确运行,需要将main函数内的代码改为:

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

总结:

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

  (2)如果想禁止类A对象被隐式转换为类B对象,可在类B中使用关键字explicit。

  

  google的c++规范中提到explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit。例如作为其他类的透明包装器的类。

  effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期的类型转换,除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit.鼓励大家遵循相同的政策。

C++11 explicit的使用的更多相关文章

  1. D3D12 图形编程

    D3D 11到D3D 12的重大改进 Direct3D 12 的编程模型和 Direct3D 11大相径庭.在Direct3D 12中,应用程序和硬件靠得近多了,这在以前是从未有过的. 这让D3D12 ...

  2. C++面试笔记(2)

    11 explicit 显式构造函数 explicit修饰的构造函数可用来防止隐式转换 class Test1 { public: Test1(int n) // 普通构造函数 { num=n; } ...

  3. Ubuntu16.04 ARM 编译 编译器版本和unordered_map map问题

    源文件内使用unordered_map时候,例如如下demo #include <unordered_map> void foo(const std::unordered_map<i ...

  4. [译] QUIC Wire Layout Specification - Frame Types and Formats | QUIC协议标准中文翻译(4) 帧类型和格式

    欢迎访问我的个人网站获取更好的阅读排版体验: [译] QUIC Wire Layout Specification - Frame Types and Formats | QUIC协议标准中文翻译(4 ...

  5. QT实现两条贪吃蛇

    Snake.pro文件 1 #------------------------------------------------- 2 # 3 # Project created by QtCreato ...

  6. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  7. C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

  8. 「C++11」Lambda 表达式

    维基百科上面对于 lambda 的引入是如下描述的: 在标准 C++,特别是当使用 C++ 标准程序库算法函数诸如 sort 和 find.用户经常希望能够在算法函数调用的附近定义一个临时的述部函数( ...

  9. Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14

    Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understa ...

随机推荐

  1. Ubuntu下,terminal经常使用快捷键

    # ctrl + l - 清屏 . cLear # ctrl + c - 终止命令. # ctrl + d - 退出 shell,好像也能够表示EOF. # ctrl + r - 从命令历史中找 . ...

  2. CASE WHEN 及 SELECT CASE WHEN的用法(写了一坨烂代码发现两条sql就行了, 哎)

    转自:http://blog.sina.com.cn/s/blog_4c538f6c01012mzt.html Case具有两种格式.简单Case函数和Case搜索函数. 简单Case函数 CASE  ...

  3. 简述MVC

    强调:mvc不是框架而是一种设计模式 分层结构的好处:1.降低了代码之间的耦合性 2.提高了代码的重用性 一. 概述 MVC的全名Model View Controller,即模型-视图-控制器的缩写 ...

  4. python实现json转excel

    import json import xlwt a = json.load(open("haha.json", encoding='utf8')) title = list(set ...

  5. rabbitMQ概念详细介绍

    1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...

  6. 修改linux 最大文件限制数 ulimit

    1)修改当前交互终端的limit值 查询当前终端的文件句柄数: ulimit -n 回车,一般的系统默认的1024. 修改文件句柄数为65535,ulimit -n 65535.此时系统的文件句柄数为 ...

  7. HDU 3999 The order of a Tree (先序遍历)

    The order of a Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. No package的问题解决

    更新pecl扩展 yum  install epel-release  //扩展包更新包yum  update //更新yum源

  9. Maven最佳实践:版本管理【转】

    什么是版本管理 首先,这里说的版本管理(version management)不是指版本控制(version control),但是本文假设你拥有基本的版本控制的知识,了解subversion的基本用 ...

  10. mongodb常用命令小结

    一.基于条件的查询 db.getCollection('monitor_log') .find({"requestUrl" : /app\/v1\/findcards\/cn/, ...