不以说明符 explicit 声明且可以单个参数调用 (C++11 前)的构造函数被称为转换构造函数(converting constructor)

与只在直接初始化(包括如 static_cast 这样的显式转换)中被考虑的 explicit 构造函数不同,转换构造函数还作为用户定义的转换序列中的一部分,在复制初始化中受到考虑。

通常说法是转换构造函数指定了一个从其实参类型(若存在)到其类类型的隐式转换。注意非 explicit 用户定义转换函数也指定一个隐式转换。

隐式声明的及用户定义的非 explicit 复制构造函数移动构造函数也是转换构造函数。

示例

运行此代码

  1. struct A
  2. {
  3. A() { } // 转换构造函数 (C++11 起)
  4. A(int) { } // 转换构造函数
  5. A(int, int) { } // 转换构造函数 (C++11 起)
  6. };
  7.  
  8. struct B
  9. {
  10. explicit B() { }
  11. explicit B(int) { }
  12. explicit B(int, int) { }
  13. };
  14.  
  15. int main()
  16. {
  17. A a1 = 1; // OK:复制初始化选择 A::A(int)
  18. A a2(2); // OK:直接初始化选择 A::A(int)
  19. A a3{4, 5}; // OK:直接列表初始化选择 A::A(int, int)
  20. A a4 = {4, 5}; // OK:复制列表初始化选择 A::A(int, int)
  21. A a5 = (A)1; // OK:显式转型进行 static_cast,为直接初始化
  22.  
  23. // B b1 = 1; // 错误:复制初始化不考虑 B::B(int)
  24. B b2(2); // OK:直接初始化选择 B::B(int)
  25. B b3{4, 5}; // OK:直接列表初始化选择 B::B(int, int)
  26. // B b4 = {4, 5}; // 错误:复制列表初始化选择了 explicit 构造函数 B::B(int, int)
  27. B b5 = (B)1; // OK:显式转型进行 static_cast,为直接初始化
  28. B b6; // OK:默认初始化
  29. B b7{}; // OK:直接列表初始化
  30. // B b8 = {}; // 错误:复制列表初始化选择了 explicit 构造函数 B::B()
  31. }