在现代C++中,explicit
关键字主要用来防止构造函数的隐式类型转换。在C++11及以后的版本中,explicit
关键字的用途得到了扩展,允许用于修饰接受一个以上参数的构造函数。这样做可以防止编译器自动执行不期望的类型转换,增加代码的安全性和可读性。下面详细介绍这一特性及其用法:
1. 单参数构造函数中的explicit
首先回顾单参数构造函数中explicit
的传统用法。
class MyClass {
public:
explicit MyClass(int x) : x(x) {}
private:
int x;
};
// MyClass obj = 10; // 错误:不能隐式转换
MyClass obj(10); // 正确
2. 多参数构造函数中的explicit
在C++11及之后,explicit
可以用于多参数构造函数,防止隐式地使用初始化列表进行类型转换。
class MyPair {
public:
explicit MyPair(int x, double y) : x(x), y(y) {}
private:
int x;
double y;
};
// MyPair p = {10, 3.14}; // 错误:不能隐式转换
MyPair p(10, 3.14); // 正确
3. 使用explicit
的构造函数中的聚合初始化
虽然explicit
可以防止通过拷贝初始化进行隐式类型转换,但它不影响直接初始化或列表初始化。
class Point {
public:
explicit Point(int x, int y) : x(x), y(y) {}
private:
int x, y;
};
// Point p = {4, 5}; // 错误:不能隐式转换
Point p{4, 5}; // 正确,使用列表初始化
4. explicit
在构造函数模板中的应用
explicit
也可以用于构造函数模板,这在模板编程中尤其有用,以避免不期望的隐式类型转换。
template <typename T, typename U>
class Pair {
public:
explicit Pair(T x, U y) : x(x), y(y) {}
private:
T x;
U y;
};
// Pair<int, double> pair = {1, 2.3}; // 错误:不能隐式转换
Pair<int, double> pair(1, 2.3); // 正确
5. 在现代C++中的explicit
转换操作符
explicit
关键字还可以用于类的转换操作符,以防止隐式转换。
class Foo {
public:
explicit operator bool() const {
return true;
}
};
Foo foo;
// bool bar = foo; // 错误:不能隐式转换
bool bar = static_cast<bool>(foo); // 正确