在 C++ 中,关键字 explicit
用于声明一个构造函数或转换操作符,以防止隐式类型转换或复制初始化。以下是 explicit
的几种常见用法:
1. 阻止隐式类型转换
当你希望构造函数只用于直接初始化,而不是隐式转换时,可以将构造函数声明为 explicit
。
class MyClass {
public:
explicit MyClass(int value) {
// 构造函数的实现
}
};
在这个例子中,MyClass
的构造函数被声明为 explicit
,这意味着不能用一个 int
类型的值来隐式创建 MyClass
对象。例如,以下代码将无法编译:
MyClass obj = 10; // 错误:不能隐式转换
2. 显式构造函数调用
当构造函数被声明为 explicit
时,你仍然可以通过直接初始化或使用 static_cast
来创建对象。
MyClass obj(10); // 正确:直接初始化
MyClass obj2 = MyClass(10); // 正确:直接初始化
MyClass obj3 = static_cast<MyClass>(10); // 正确:显式转换
3. 转换操作符
explicit
也可以应用于类型转换操作符。
class MyClass {
public:
explicit operator int() const {
// 类型转换的实现
}
};
在这个例子中,operator int()
被声明为 explicit
,这意味着不能隐式地将 MyClass
对象转换为 int
类型。但是,你可以使用 static_cast
来显式转换。
4. C++11 中的列表初始化和 explicit
在 C++11 及以后的版本中,如果构造函数只接受一个参数,并且该参数可以被直接初始化,那么即使构造函数是 explicit
的,也可以使用花括号 {}
进行列表初始化。
MyClass obj{10}; // 正确:C++11 中的列表初始化
5. 复制或移动构造函数
对于复制或移动构造函数,explicit
关键字不起作用,因为复制或移动构造总是直接初始化。
class MyClass {
public:
explicit MyClass(const MyClass& other) {
// 复制构造函数的实现
}
MyClass(MyClass&& other) {
// 移动构造函数的实现
}
};
MyClass obj1(obj); // 正确:复制初始化
MyClass obj2 = obj; // 正确:复制初始化
MyClass obj3 = std::move(obj); // 正确:移动初始化
使用 explicit
关键字可以帮助你避免不安全的隐式类型转换,并使你的代码更加清晰和安全。