C++中explicit关键字的用法

explicit关键字主要用在防止隐式类型转换的发生。下面将结合具体的例子分析类型转换场景中发生了什么,以及explicit关键字的意义所在。

隐式类型转换

先看下面这个例子:

#include <iostream>
using namespace std;

//定义了一个商品类
class Goods {
    
private:
    string goodsId;   //商品id
    float price;      //商品价格
public:
    //构造函数中仅需传入ID即可,因为价格默认为0元
    Goods(string ID, float prc = 0.0f) : goodsId(ID), price(prc) {} 
    //对照两商品id判断是否为同一款商品
    bool sameGoods(const Goods &another) {
        return this->goodsId == another.goodsId;
    }
};

int main() {
    Goods bread("6901234", 6.0);
    Goods choc("6904321", 8.0);
    Goods str = string("6901234");  //通过string对str进行了初始化
    
    //与Goods对象对比,不会发生转换
    cout<< bread.sameGoods(choc)<< endl;
    //传入一个string类型,将通过Goods的构造函数发生隐式类型转换
    cout<< bread.sameGoods(str)<< endl;  

    return 0;
}

上例运行的结果为:0 1,即虽然第二次比较传入的参数是一个string类型,但是没有报错。

因为C++编译器希望程序能够正常运行,当遇到 Goods str = string("6901234"); 这样的“无礼”要求,编译器首先将查找Goods类中是否包含类似Goods(str)的构造函数,从而将string类型转化为Goods类型(构造了一个Goods的临时对象)。此时,便发生了隐式类型转换,而产生的临时对象也是在C++中产生BUG的来源之一。

explicit用法

        为了避免编译器在没有提醒我们的同时进行隐式类型转换,在可能发生转换的构造函数前加上explicit关键字。被explicit关键字修饰了构造函数之后,只能进行显式的类型转换,即用户需要显式创建临时对象。我们将刚才的Goods构造函数加上explicit修饰:

#include <iostream>
using namespace std;

class Goods {
    
private:
    string goodsId;   //商品id
    float price;      //商品价格
public:
    //使用explicit修饰构造函数
    explicit Goods(string ID, float prc = 0.0f) : goodsId(ID), price(prc) {} 
    
    bool sameGoods(const Goods &another) {
        return this->goodsId == another.goodsId;
    }
};

int main() {
    Goods bread("6901234", 6.0);
    Goods str = string("6901234");

    cout<< bread.sameGoods(str)<< endl;

    return 0;
}

此时,系统将提示"不存在用户定义的从 \"std::string\" 到 \"Goods\" 的适当转换"。

结语:

1.隐式类型转换会发生在构造函数可以使用一个实参进行调用(可能含有其他参数,且其他参数是默认参数)时;

2.隐式类型转换会生成临时对象,有可能造成错误,需要避免;

3.可以用explicit关键字修饰可能发生隐式类型转换的构造函数;

最后是一段写自《Effective C++》中的一段话:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值