C++的explicit关键字

C++程序员对于explicit这个关键字其实不是很熟悉,至少我是如此;缘由在于其使用范围不大,并且做用也没有那么大。
可是这不是说明咱们的程序中不须要这个关键字,按Google的C++编程规范和Effective C++的推荐看,咱们最好将只有一个参数的构造函数都加上这个关键字,这同时也是cppcheck的要求。c++

explicit意味着明确的,肯定的,这代表这个构造函数是没法隐式转换的,其反义词正式implicit。没有了隐式转换,咱们则须要显式使用某个类型的构造函数,如此,能够规避不少不那么能拿得出手的外部类的调用。程序员

指定构造函数或转换函数(从c++ 11开始)是显式的,也就是说,它不能用于隐式转换和复制初始化编程

一个构造函数只有一个非默认参数(从c++ 11开始),没有explicit声明的,称为转换构造函数。ide

咱们来看一个使用explicit 的代码函数

class explicitConstruct
{
public:
    explicitConstruct();
    explicitConstruct(int i){
        std::cout << "we use interger parameter is "<<i <<"\n";
    }
    explicitConstruct(int i,int j) {
        std::cout << "we use double interger parameter is "<<i<<" and "<<j<<"\n";
    }

};

class explicitConstructB
{
public:
    explicit explicitConstructB(int i){
        std::cout << "we use explicit explicitConstructB interger parameter is "<<i <<"\n";
    }
    explicit explicitConstructB(int i,int j){
        std::cout << "we use explicit explicitConstructB double interger parameter is "<<i<<" and "<<j<<"\n";
    }
    
};
};

explicitConstruct和explicitConstructB类的惟一区别是explicitConstructB的构造函数加入了explicit。
如下是测试代码测试

explicitConstruct i(3);//ok
explicitConstruct j(3,4); //ok
explicitConstructB ii(3);//ok
explicitConstructB jj(3,4);//ok

explicitConstruct k = 3;//ok
explicitConstruct l = {3,4};//ok

// explicitConstructB kk = 3; //error! copy-initialization does not consider explicitConstructB::explicitConstructB(int)
// explicitConstructB ll = {3,4};///error! copy-initialization does not consider explicitConstructB::explicitConstructB(int,int)
explicitConstructB kkk = explicitConstructB(3);//ok
explicitConstructB lll = explicitConstructB(3,4);//ok

测试代码很清楚的说明了explicit关键字发挥的做用,即让类对象的构造过程没法使用隐式转换的方式调用拷贝初始化。这样作的好处在于,咱们能够严格控制构造器参数的类型,避免发生歧义。code