C++ explicit 关键字的作用是禁止只有一个参数的构造函数发生默认的隐式转换(或者除第一个参数外,其它参数都有默认值),如下面的代码:

#include <iostream>
using namespace std;

class TestExplicit
{
public:
    TestExplicit(double dVal)
        :m_dVal(dVal)
    {
    }

    ~TestExplicit(){}

private:
    double m_dVal;
};

int main()
{
    TestExplicit obj1(5);
    TestExplicit obj2 = 12.2;  // 编译正常,运行时将12.2赋值给m_dVal
    TestExplicit obj3 = 'd';   // 编译正常,运行时将'd'的ascⅡ 100赋值给m_dVal

    return 0;
}

上面的代码像TestExplicit obj2 = 12.2; 运行时进行了隐式转换,类似于TestExplicit obj2 = TestExplicit(12.2);

像这种直接赋值是没有问题的,但是有的时候是会有问题的,比如传进去的值不是要进行赋值,而是进行内存分配的时候。这种隐式转换就会引起问题,因为隐式转换可能会将一些不正确的参数进行转换,这时候编译是不会报错的,但是运行的时候就会有问题,那个时候再来排查问题就会比较麻烦了。

现在把上面的例子改一下,在构造函数中加入explicit关键字,来显式禁用隐式转换。把构造函数改为如下:

    explicit  TestExplicit(double dVal)
        :m_dVal(dVal)
    {
    }

这个时候这两行在编译的时候就会报错了:

    TestExplicit obj2 = 12.2;  // 编译报错
    TestExplicit obj3 = 'd';   // 编译报错

我理解这样做的目的就是把错误尽量在编译的时候发现,越早发现排查的成本越低。