explicit关键字
隐式类类型转换
在C++语言中,类中的构造函数如果只含有一个参数,默认情况下存在一种隐式转换,即定义了转换为此类类型的隐式转换机制。然而,这种机制并非总是合理的,甚至容易产生错误,因此,新标准增加了explicit关键字,用来限制隐式转换。
下面的示例是隐式转换的机制:
class Test {
public:
Test(); // 空构造函数
Test(double a); // 含一个参数的构造函数
Test(int a, int b); // 含两个参数的构造函数
Test(int a, double b = 1.2); // 带有默认初始值的构造函数
~Test();
};
// 调用
Test d1(12.3); // 直接调用含一个参数的构造函数
Test d2 = 1.2; // 也是调用含有一个参数的构造函数,但是包含一次隐式转换
Test d3(12, 13);
Test d3 = 12; // 隐式转换,调用带有默认初始值的构造函数Test(int a, double b = 1.2)
上例中,Test d2 = 1.2; 就是进行了一次隐式转换,其转换方式是先创建一个临时对象,再对d2进行赋值,即下面的方式:
Test temp(1.2); // 创建临时变量
d2 = temp; // 进行赋值操作
Test d3 = 12;实际上调用的是含有两个参数,但是其中一个带有默认值的构造函数,也可以进行隐式转换。
explicit关键字
explicit可以阻止构造函数的隐式转换,但是只能对含有一个参数,或者有n个参数,但是其中 n-1 个参数是带有默认值的构造函数有效,其余的构造函数,explicit无法进行约束。
下面代码是explicit的使用:
class Test {
public:
Test() {} // 空构造函数
explicit Test(double a); // 该构造函数无法进行隐式类类型转换
explicit Test(int a, int b); // 含有两个参数,explicit对其无效,然而该构造函数本身也是不能隐式转换的
explicit Test(int a, double b = 1.2); // 该构造函数无法进行隐式类类型转换
~Test() {}
};
// 调用
Test d1(12.3); // 正确
Test d2 = 1.2; // 错误,不能进行隐式类类型转换
Test d3(12, 13); // 正确
Test d3 = 12; // 错误,不能进行隐式类类型转换
使用关键字explicit之后,构造函数就不能进行隐式类类型转换,但是其本身还是可以进行double向int类型的显示类型转换的。