explicit 主要防止单参数构造函数引发的隐式类型转换,包括拷贝初始化(如 String s = "hello")、函数传参(如 func("world"))等场景;它不阻止显式调用或直接初始化。

explicit 用来禁止编译器执行单参数构造函数的隐式类型转换。
它主要防止哪些隐式转换?
当类有一个只接受一个参数的构造函数(或有默认值、能用一个参数调用的构造函数)时,编译器可能自动用该参数“悄悄”构造对象。explicit 就是告诉编译器:不许这样干。
- 比如
String s = "hello";—— 如果 String 有String(const char*)构造函数且没加 explicit,这行会隐式调用构造函数;加了 explicit 后,这行直接报错。 - 函数传参时也会触发:如果函数形参是
String,你传入"world",没 explicit 就会自动转成 String 对象;加了 explicit 就必须显式写成func(String("world"))。 - 拷贝初始化(
=形式)受影响,直接初始化(String s("hello"))不受影响。
什么时候该加 explicit?
只要这个单参数构造函数的语义不是“类型等价转换”,就建议加上。典型场景:
- 资源封装类(如
FileHandle(int fd))—— 你不会希望整数被悄悄变成文件句柄。 - 数值包装类(如
Money(double amount))——Money m = 99.9;看似方便,但容易掩盖精度丢失或单位混淆问题。 - 任何你不想让用户“无意中”构造对象的地方。
注意几个细节
explicit 只对单参数构造函数(含可变参但实际只用一个参数的情况)有效;多参数构造函数本来就不会隐式调用,所以 explicit 对它们无意义(C++11 起允许给多参构造函数加 explicit,用于禁止大括号隐式转换,但那是另一回事)。
立即学习“C++免费学习笔记(深入)”;
它不阻止显式调用,也不影响赋值运算符重载。
基本上就这些。加 explicit 不是限制能力,而是让接口更清晰、错误更早暴露。









