【C++】关键字 explicit

摘要

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

跟它相对应的另一个关键字是 implicit ,意思是隐藏的,类构造函数默认情况下即声明为 implicit (隐式)

浅显的理解

C++中,一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数),承担了两个角色:

  • 构造器
  • 默认且隐含的类型转换操作符

所以,有时候在我们写下如 AAA = XXX,这样的代码,且恰好XXX的类型正好是AAA单参数构造器的参数类型,这时候编译器就自动调用这个构造器,创建一个AAA的对象

这样看起来好象很酷,很方便。但在某些情况下(见下面权威的例子),却违背了我们(程序员)的本意。这时候就要在这个构造器前面加上 explicit 修饰,指定这个构造器只能被明确的调用/使用,不能作为类型转换操作符被隐含的使用

class A {
private:
    int a;
public:
    A(int x = 0){ //普通构造函数
        a = x;
    }
};

class B {
private:
    int a;
public:
    explicit B(int x = 0){ //explicit(显式)构造函数
        a = x;
    }
};

int main() {
    A a1 = 10; //正确,隐式调用构造函数
    B b1 = 10; //错误,explicit修饰,不能隐式调用
               //编译错误: error: conversion from 'int' to non-scalar type 'B' requested
    A a2(10);  //正确,显式调用构造函数
    B b2(10);  //正确,显式调用构造函数
}

explicit 补充

在 C++11 新标准中引入了显式的类型转换运算符(explicit conversion operator)

explicit 的功能在这里和显式的构造函数一样,编译器(通常)也不会将一个显式的类型转换运算符用于隐式类型转换

class SmallInt {
private:
    std::size_t val;
public:
    SmallInt(int i = 0): val(i) {...}; // 构造函数
    //...其他成员的定义

    //编译器不会自动执行这一类型转换
    explicit operator int() const { return val; } //显式的类型转换函数

};

SmallInt si = 3; //正确:SmallInt的构造函数不是显式的
si = 4;          //正确:首先将4隐式地转换成SmallInt,然后调用SmallInt::operator=
si + 3;          //错误:此处需要隐式的类型转换,但类的运算符是显式的
                 //如果前面没有explicit,那么这里首先将si隐式转换地转换成int,然后执行整数的加法
static_cast<int>(si) + 3; //正确:显式地请求类型转换

当类型转换运算符是显式的时,我们也能执行类型转换,不过必须通过显式的强制类型转换才可以。

注意:该规定存在一个例外,即如果表达式被用作条件,则编译器会将显式的类型转换自动应用于它。换句话说,当表达式出现在下列位置时,显式的类型转换将被隐式地执行:

  • if、while 及 do 语句地条件部分
  • for 语句头地条件表达式
  • 逻辑非运算符(!)、逻辑或运算符(||)、逻辑与运算符(&&)的运算对象
  • 条件表达式(? :)的条件表达式

参考资料

[1] C++ Primer(第5版)中文版 p514 类型转换运算符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值