跳转至

💡 一分钟速览:用可编译示例说明 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++ explicit:构造函数、operator bool 与 explicit(bool) | C++那些事

相关主题

评论