语言基础(6):关键字explicit

1、explicit含义

C++中 explicit 被用来修饰只有一个参数的构造函数,作用是调用该构造函数必须是显示的(且要求只能放在函数声明处), 跟它相对应的单词是 implicit(隐含的、不言明的), 类构造函数默认情况下即声明为 implicit (因此C++没有此关键字)。

如果不使用该关键字,调用只有一个参数的构造函数允许通过缺省的转换操作完成,过程可能通过如下两步执行(VS2017验证不是):

  • 将该构造函数参数对应数据类型的数据转换为该类对象;
  • 然后调用复制构造函数来实现构造对象;

通过一个例子来说明 explicit 作用:

class String{
      explicit String(int n);
      String(const char *p);
};
String s1 = 'a';       // 错误:不能做隐式char->String转换
String s2(10);        // 可以:调用explicit String(int n);
String s3 = String(10);   // 可以:调用explicit String(int n);再调用默认的复制构造函数
String s4 = "Brian";       // 可以:隐式转换调用String(const char *p);再调用默认的复制构造函数
String s5("Fawlty");       // 可以:正常调用String(const char *p);

void f(String);

String g()
{
    f(10);         // 错误:不能做隐式int->String转换
    f("Arthur");   // 可以:隐式转换,等价于f(String("Arthur"));
    return 10;    // 错误:不能做隐式int->String转换
}

#2、例外的情况
前面说过,该参数只对有一个参数的构造函数有效,对于无参数和多个参数的构造函数,因为他们只能通过显示调用,所以使用 explicit 没有任何意义,但也存在例外情况,如下代码:
```
// Example.h
#pragma once
class CExample
{
public:
CExample(void);
public:
~CExample(void);
public:
int m_iFirst;
int m_iSecond;
public:
CExample(int iFirst, int iSecond = 0);
};

// Example.cpp

include "Example.h"

CExample::CExample(void): m_iFirst(0) { }
CExample::~CExample(void) { }
CExample::CExample(int iFirst, int iSecond):m_iFirst(iFirst), m_iSecond(iSecond)

//TestExplicitKey.cpp
...//其它头文件

include "Example.h"

int main()
{
CExample objOne; // 调用没有参数的构造函数
CExample objTwo(12, 12); // 调用有两个参数的构造函数
CExample objThree(12); // 同上,可以传一个参数是因为该构造函数的第二个参数有默认值
/* 执行了隐式转换,等价于CExample temp(12);objFour(temp);注意这个地方调用了编译器为我们提供的默认复制构造函数 */
CExample objFour = 12;
return 0;
}

如果在构造函数声明中加入关键字explicit,如下:
`explicit CExample(int iFirst, int iSecond = 0);`
那么 CExample objFour = 12; 这条语句将不能通过编译。在vs下的编译错误提示如下:

error C2440: 'initializing' : cannot convert from 'int' to 'CExample'
Constructor for class 'CExample' is declared 'explicit'

<br/>
#3、何时不用explicit
当我们需要隐式转换的时候,比如说String类的一个构造函数:
`String(const char*);`
定义成这样的好处,在需要隐式转化的时候编译器会自动地帮我们转换,标准库里面的String就是一个好的证明。具体来说:
我们可以这样

String str="helloworld"; // 直接调用构造函数

String str="hello"+str+"world";
// 调用重载的+操作符号,此过程相当于:
String temp("hello"); // 调用构造函数
String str=temp+str;
String t("world"); // 调用构造函数
String str=str+t;

<br/>
#总结
<table><tr><td bgcolor = #233333><font color = #DDFFDD>
1. explicit关键字只需用于类内的单参数构造函数前面,由于无参数的构造函数和多参数的构造函数总是显示调用,这种情况在构造函数前加explicit无意义;<br/>
2. google的c++规范中提到explicit的优点是可以避免不合时宜的类型变换,缺点无。所以google约定所有单参数的构造函数都必须是显示的,只有极少数情况下拷贝构造函数可以不声明称explicit (例如作为其他类的透明包装器的类或者需要隐式转换的情况);<br/>
3. effective c++中说:被声明为explicit的构造函数通常比其non-explicit兄弟更受欢迎。因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非我有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit,鼓励大家遵循相同的政策;<br/>
</font></td></tr></table>

原文链接: https://www.cnblogs.com/wnwin/p/10697405.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    语言基础(6):关键字explicit

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/265257

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午5:05
下一篇 2023年2月14日 下午5:06

相关推荐