iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >老生常谈C++explicit关键字
  • 875
分享到

老生常谈C++explicit关键字

C++explicit关键字C++explicit 2023-03-24 11:03:50 875人浏览 八月长安
摘要

目录显式和隐式的区别总结explicit 关键字用于显式声明一个类构造函数是显式而非隐式的,从而禁用类构造函数的隐式自动类型转换。类构造函数默认情况下即声明为implici

explicit 关键字用于显式声明一个类构造函数是显式而非隐式的,从而禁用类构造函数的隐式自动类型转换。类构造函数默认情况下即声明为implicit(隐式)。

explicit关键字仅能用于只有1个参数的类构造函数,或者第二个参数及之后的所有参数都有默认值的类构造函数。

显式和隐式的区别

class CxString  // 没有使用explicit关键字的类声明, 即默认为隐式声明  
{  
public:  
    char *_pstr;  
    int _size;  
    CxString(int size)  
    {  
        _size = size;                // string的预设大小  
        _pstr = malloc(size + 1);    // 分配string的内存  
        memset(_pstr, 0, size + 1);  
    }  
    CxString(const char *p)   
    {  
        int size = strlen(p);  
        _pstr = malloc(size + 1);    // 分配string的内存  
        strcpy(_pstr, p);            // 复制字符串  
        _size = strlen(_pstr);  
    }  
    // 析构函数这里不讨论, 省略...  
};  
  
    // 下面是调用:  
    CxString string1(24);     // 这样是OK的, 为CxString预分配24字节的大小的内存  
    CxString string2 = 10;    // 这样是OK的, 为CxString预分配10字节的大小的内存  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码  
    string1 = 2;              // 这样也是OK的, 为CxString预分配2字节的大小的内存  
    string2 = 3;              // 这样也是OK的, 为CxString预分配3字节的大小的内存  
    string3 = string1;        // 这样也是OK的, 至少编译是没问题的, 但是如果析构函数里用free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放  

上面的代码中, "CxString string2 = 10;" 这句为什么是可以的呢? 在c++中, 如果的构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的类型转换:将该构造函数对应数据类型的数据转换为该类对象. 也就是说 "CxString string2 = 10;" 这段代码, 编译器自动将整型转换为CxString类对象, 实际上等同于下面的操作:

CxString string2(10);   
//或  
CxString temp(10);  
CxString string2 = temp;

但是, 上面的代码中的_size代表的是字符串内存分配的大小, 那么调用的第二句 "CxString string2 = 10;" 和第六句 "CxString string6 = 'c';" 就显得不伦不类, 而且容易让人疑惑,这使得默认的 implicit 构造函数存在一些隐患

需要使用 explicit 关键字禁用类构造函数的隐式自动类型转换,这样编译器能给出报错:

class CxString  // 使用关键字explicit的类声明, 显示转换  
{  
public:  
    char *_pstr;  
    int _size;  
    explicit CxString(int size)  
    {  
        _size = size;  
        // 代码同上, 省略...  
    }  
 
    CxString(const char *p)  
    {  
        // 代码同上, 省略...  
    }  
};  
    // 下面是调用:  
    CxString string1(24);     // 这样是OK的  
    CxString string2 = 10;    // 这样是不行的, 因为explicit关键字取消了隐式转换  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样是不行的, 其实调用的是CxString(int size), 且size等于'c'的ascii码, 但explicit关键字取消了隐式转换  
    string1 = 2;              // 这样也是不行的, 因为取消了隐式转换  
    string2 = 3;              // 这样也是不行的, 因为取消了隐式转换  
    string3 = string1;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载  

explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了。例如:

class CxString  // explicit关键字在类构造函数参数大于或等于两个时无效  
{  
public:  
    char *_pstr;  
    int _age;  
    int _size;  
    explicit CxString(int age, int size)  
    {  
        _age = age;  
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {  
        // 代码同上, 省略...  
    }  
};  
  
    // 这个时候有没有explicit关键字都是一样的  

但是, 也有一个例外, 就是当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数时, 等效于只有一个参数的类构造函数, 因此仍符合explicit作用的场景。例子如下:

class CxString  // 使用关键字explicit声明  
{  
public:  
    int _age;  
    int _size;  
    explicit CxString(int age, int size = 0)  
    {  
        _age = age;  
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {  
        // 代码同上, 省略...  
    }  
};  
 
    // 下面是调用:   
    CxString string1(24);     // 这样是OK的  
    CxString string2 = 10;    // 这样是不行的, 因为explicit关键字取消了隐式转换  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数  
    string1 = 2;              // 这样也是不行的, 因为取消了隐式转换  
    string2 = 3;              // 这样也是不行的, 因为取消了隐式转换  
    string3 = string1;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载  

总结

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

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

effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。

到此这篇关于老生常谈C++ explicit关键字的文章就介绍到这了,更多相关C++ explicit关键字内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 老生常谈C++explicit关键字

本文链接: https://www.lsjlt.com/news/201117.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 老生常谈C++explicit关键字
    目录显式和隐式的区别总结explicit 关键字用于显式声明一个类构造函数是显式而非隐式的,从而禁用类构造函数的隐式自动类型转换。类构造函数默认情况下即声明为implici...
    99+
    2023-03-24
    C++ explicit关键字 C++ explicit
  • C++之explicit关键字
    目录一、单参构造函数二、多参构造函数👉构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用 一、单参构造函数 还是老朋...
    99+
    2023-05-15
    C++ explicit关键字 explicit关键字 C++ explicit
  • C++explicit关键字讲解
    目录1 隐式转换2 显示转换前言: C++编码时,可以通过构造函数将相应的数据类型转换成为C++类的对象,从某种程度来说给编码带来了方便,但并不是每次都正确,为了避免这种情况,C++...
    99+
    2022-11-12
  • C++中explicit关键字怎么用
    这篇文章给大家分享的是有关C++中explicit关键字怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1 隐式转换C++ 构造函数默认类型为implicit,定义时既可以显示说明也可以默认不加该标识符。//...
    99+
    2023-06-22
  • C++中的explicit关键字详解
    目录前言1. 抑制构造函数定义的隐式转换2. 为转换显式地使用构造函数3. 类型转换运算符可能产生意外结果4. 显示的类型转换运算符5. explicit练习5.1 当不使用expl...
    99+
    2022-11-13
  • C++ Explicit关键字详细解析
    explicit关键字用来修饰类的构造函数,表明构造函数是显示的,相对的是implicit关键字。首先这个关键字只能用在类内部的构造函数声明上,而不能用在类外部的函数定义上,它的作用...
    99+
    2022-11-15
    Explicit 关键字
  • C++ explicit关键字怎么使用
    这篇“C++ explicit关键字怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++ exp...
    99+
    2023-07-05
  • C++ explicit关键字的使用详解
    在C++中,我们有时可以将构造函数用作自动类型转换函数。但这种自动特性并非总是合乎要求的,有时会导致意外的类型转换,因此,C++新增了关键字explicit,用于关闭这种自动特性。即...
    99+
    2022-11-12
  • C++中如何使用 explicit关键字
    这期内容当中小编将会给大家带来有关C++中如何使用 explicit关键字,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有&...
    99+
    2023-06-17
  • 老生常谈C++ 中的继承
    目录继承1.1 继承的概念1.2 继承的定义1.2.1 定义格式2 基类(父类)对象和派生类(子类)对象之间的赋值转换 3 继承中的作用域4 派生类(子类)的默认成员函数5...
    99+
    2022-11-12
  • 老生常谈python字典用法
    目录创建字典遍历访问修改删除setdefault() 方法创建字典 python 创建字典可以使用 dict 函数,或者使用花括号,用花括号的方式更为常见。 d = { ...
    99+
    2022-11-12
  • C++中explicit关键字的作用是什么
    本篇文章为大家展示了C++中explicit关键字的作用是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。如果C++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对...
    99+
    2023-06-17
  • 老生常谈c++中的静态成员
    引言 有时候需要类的一些成员与类本身相关联,而不是与类的每个对象相关联。比如类的所有对象都要共享的变量,这个时候我们就要用到类的静态成员。 声明类的静态成员 声明静态成员的方法是使用...
    99+
    2022-11-12
  • 老生常谈C语言链表小结
    目录链表的概念及结构概念结构链表的分类单链表的实现(无头)双向链表的实现总结:链表和顺序表的区别链表的概念及结构 概念 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的...
    99+
    2022-11-12
  • c++中explicit与mutable关键字的深入探究
    今天说一说c++里面的两个关键字explicit和mutable。 1. explicit关键字 在写c++标准输入输出相关文章,查看iostream实现代码的时候,经常看到构造函...
    99+
    2022-11-12
  • C语言函数指针的老生常谈
    目录函数指针函数指针的应用函数指针作为参数实例(qsort函数)总结 函数指针 本质上是一个指针,只不过指向函数而已。 编译器在编译期间对函数开辟了一块空间,而这快空间的开始地址,就...
    99+
    2022-11-12
  • 老生常谈C语言中指针的使用
    目录前提一.指针基础1.1 变量指针1.2 数据指针1.3 指针的本质1.4 指针数组1.5 指针的移动1.5 Scanf函数的解释二.指针的进阶玩法2.1 二维指针2.2 结构体指...
    99+
    2022-11-13
  • 老生常谈Java字符串进阶(必看篇)
    前言最常用的对字符串操作的类有三个,分别是String,StringBuilder,StringBuffer,下面将会详细的说说这三个类......StringString类代表字符串,这个是最基本的对字符串的类,这个也是使用比较多的类,这...
    99+
    2023-05-31
    java 字符串 进阶
  • C++中怎么利用explicit关键字实现构造函数
    这篇文章给大家介绍C++中怎么利用explicit关键字实现构造函数,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如果C++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数...
    99+
    2023-06-17
  • 初识C++的const关键字,常量与常变量
    目录C语言的const1.const关键字2.const修饰的只读变量3.节省空间,避免不必要的内存分配,同时提高效率4.使用cosnt修饰4.1修饰一般变量4.2修饰数组4.3修饰...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作