💡 一分钟速览:用可编译示例说明 C++ explicit 如何阻止隐式转换、直接初始化与复制初始化的区别,以及 C++20 explicit(bool) 的用法。
最后更新:2026-10-13
C++ explicit:构造函数与转换函数¶
当自动转换会掩盖类型含义时,用 explicit 要求调用者明确写出转换。它可以修饰构造函数和转换函数,不能修饰普通成员函数。直接初始化仍可调用显式构造函数,隐式转换不能。
直接初始化与复制初始化¶
#include <type_traits>
struct UserId {
explicit UserId(int n) : value(n) {}
int value;
};
void load(UserId) {}
int main() {
UserId a(42); // 正确:直接初始化
UserId b{42}; // 正确:直接列表初始化
load(UserId{42}); // 正确:显式构造实参
// UserId c = 42; // 错误:复制初始化
// load(42); // 错误:不能隐式地把 int 转为 UserId
// UserId d = {42}; // 错误:复制列表初始化
static_assert(!std::is_convertible_v<int, UserId>);
return a.value != b.value;
}
用 c++ -std=c++17 -Wall -Wextra explicit.cpp 编译。可一次取消一行错误示例的注释,观察诊断。explicit 并没有禁用构造函数,只是要求调用者明确写出构造动作。ID、单位、句柄等类型尤其适合这样设计。
explicit operator bool 与条件判断¶
struct Connection {
explicit operator bool() const { return connected; }
bool connected = true;
};
int main() {
Connection c;
if (c) { // 正确:条件语境允许转换到 bool
bool ready = static_cast<bool>(c); // 正确:显式转换
return ready ? 0 : 1;
}
// bool ready = c; // 错误:普通复制初始化
return 1;
}
if (c) 中的条件会进行特殊的“按语境转换到 bool”;这不意味着 c 在所有表达式中都能隐式转为 bool。连接、文件句柄、可选值等具有“是否可用”状态的类型可以考虑这种写法。
C++20:条件式 explicit(bool)¶
泛型包装类型有时需要根据条件决定能否隐式转换。C++20 起,explicit(condition) 的常量表达式为真时表示显式,为假时允许隐式转换。
#include <type_traits>
template<bool AllowImplicit>
struct Number {
explicit(!AllowImplicit) Number(int n) : value(n) {}
int value;
};
static_assert(std::is_convertible_v<int, Number<true>>);
static_assert(!std::is_convertible_v<int, Number<false>>);
int main() {
Number<true> a = 7; // 正确:explicit(false)
Number<false> b{7}; // 正确:直接初始化
// Number<false> c = 7; // 错误:explicit(true)
return a.value != b.value;
}
用 c++ -std=c++20 -Wall -Wextra explicit20.cpp 编译。若没有条件行为,直接写 explicit 更清楚。
如何选择¶
| 情况 | 建议 |
|---|---|
| ID、单位等不应被普通整数或字符串悄悄替代 | 将转换构造函数标记为 explicit |
| 类型存在明确的可用/不可用状态 | 考虑 explicit operator bool() |
| 泛型包装类型需要有条件地允许隐式转换 | C++20 中使用 explicit(condition) |
本文扩展了原有的仓库示例。相关设计选择可继续阅读 struct 与 class和初始化与赋值。
参考资料¶
关于作者¶
个人公众号:

相关主题¶
- C++ 纯虚函数与抽象类 | C++那些事
- C++ assert 断言 | C++那些事
- C++ 位域 | C++那些事
- C 语言实现 C++ 多态 | C++那些事
- C++ const 详解:常量、常量指针与指针常量的区别 | C++那些事
- C++ const 全家桶 | C++那些事
- C++ 解引用运算符 * | C++那些事
- C++ 初始化与赋值 | C++那些事
- C++ 多返回值写法 | C++那些事
- C++ mutable 关键字 | C++那些事