构造函数解析顺序的问题

pip*_*pex 7 c++ overloading operator-overloading implicit-conversion

考虑以下T的构造函数:

struct T {
    T(const bool) { std::cout << "T(const bool)" << endl; }
    T(const std::string&) { std::cout << "T(const std::string&)" << endl; }
};

T t("");
Run Code Online (Sandbox Code Playgroud)
  1. 为什么在构造t时T(const bool)优先考虑T(const std::string&)
  2. 由于上述优先级可能会导致混淆期望T(const std::string&)被调用的用户,T(const std::string&)在将字符串文字传递给T的构造函数时,我可以做什么来隐式调用.现在,我发现的唯一工作是添加另一个构造函数,最高优先权:

    T(const char* s)
    {
        std::cout << "T(const char*)" << endl;
        *this = std::string(s);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 除了上述解决方案之外,声明explicit T(const bool)避免混淆并不能解决上述问题:在这种情况下,虽然T t = ""现在已被禁止,为什么表格T t("")仍然被允许并打电话T(const bool)

Jam*_*lis 8

为什么在构建时T(const bool)优先考虑?T(const std::string&)t

""属于char[1]; 这可以char const*通过数组到指针的转换隐式转换.指针可以隐式转换为bool,所有非空指针都会变为true空指针false.这些都是"内置"标准转换.

char const* -> std::string转换是用户声明的转换:它利用的转换构造std::string,需要一个char const*.

在重载解析期间,标准("内置")转换比用户声明的转换更受欢迎,因此构造函数在bool此处的匹配比获取的更好std::string.

目前我发现的唯一工作是添加另一个构造函数

这听起来像是合理的解决方案; 对于您描述的简单场景,当然是最直接的解决方案.但是,你对作业的使用*this有点笨拙; 将两个构造函数委托给某些初始化函数会更好.

或者,您可以将模板enable_if用于任何您想要禁止转换的构造函数:

template <typename U>
T(U, std::enable_if<std::is_same<U, bool>::value>::type* = 0) { }
Run Code Online (Sandbox Code Playgroud)

此构造函数只能使用bool参数调用,而不能使用其他任何内容.你可以找到enable_ifis_same在加速,C++ TR1,或C++ 0x中.您还可以使用!is_pointer,is_integral或其他类型特征的组合来允许其他一些参数类型但不允许char const*.

或者,作为另一种选择,你可能会避开bool完全与相应的普查员使用自己的枚举true,并false为构造函数.这是否有意义取决于您的使用案例.

声明explicit T(const bool)要避免不解决上述问题...为什么表单T t("")仍然被允许并且确实调用了T(const bool)

explicit只允许隐式转换为T. T t("");根本没有转换T; 它t通过构造它来直接初始化对象,并将参数""传递给最佳匹配的构造函数.