explicit关键字是禁止隐式调用构造函数。什么是隐式调用构造函数呢,先看下面一个简单例子。
struct test1
{
//explicit
test1(int a, int b = 0) : x(a), y(b){}
test1 operator+(const test1 &t)
{
return test1(x + t.x, y + t.y);
}
int x, y;
};
int main()
{
test1 x(5, 6);
test1 x1 = x + 1;
cout << x1.x << ' ' << x1.y << endl;
return 0;
}
代码中位于主函数内,可以看到有一个+运算,这里的+运算可能会引起不少人的注意。有些小伙伴可能会问:类内没有声明+运算符可以和int数值计算呀,为什么要这么写?这么写能编译通过吗?
其实这段代码是可以编译通过并且正确运行的,其运行结果输出为6 6。
下面来解释一下这段代码为什么可以通过:
这段代码中,巧妙的使用了test1这个类的构造函数,注意看这个构造函数,他需要两个参数,但是呢,第二个参数可以选填。这样一来,这个类构造时,传入一个参数,也是可以创建一个对象的。在调用operator+的时候,由于后面是一个数字,而这个数字恰好可以转换为test1类对象,因此,这里编译器会隐式的调用类的构造函数,这一行代码经过编译器处理后,可以理解为下面这样
test1 x1 = x + test1(1);
编译器还是非常智能的,他已经会把能匹配到的构造函数自动调用起来,但是有些时候,我们设计的类可能并不希望其隐式调用,那怎么办呢?就需要用到C++中一个关键字:explicit。
当我们将上面代码中explicit取消掉注释的时候,这段代码编译时就会报错,这样就防止了编译器太过智能,隐式调用构造函数的问题了。
在C++11之前,explicit只能防止上面说的这样,构造函数可以传入一个参数的情况。从C++11版本开始,explicit也可以防止构造函数传递多个参数的时候,使用初始化列表进行隐式调用。下面为C++11的示例
struct test2
{
test2(int a, int b) { cout << "test2(int a,int b)..." << endl; }
explicit test2(int a, int b, int c) { cout << "explicit 3 args version" << endl; }
};
void test2_fun(const test2 &x)
{
cout << "test2_fun()" << endl;
}
int main()
{
test2 t2_1(1, 1);
test2 t2_2{1, 2};
test2 t2_3{3, 3, 3};
test2 t2_4 = {4, 4};
//test2 t2_5 = {5, 5, 5}; // 报错,编译器不允许隐式调用构造
test2_fun(t2_3);
test2_fun({1, 2});
//test2_fun({1,2,3}); // 报错,编译器不允许隐式调用构造
return 0;
}