显式错误类型的构造函数

gni*_*ola 7 c++ constructor c++11 c++14

在下面的示例中,我的输出是"single param ctor",两次.我的问题是双重的,首先,为什么叫而不是包含字符串版本的布尔构造函数,和第二,有没有办法让不叫铸造呼叫的字符串版本?

顺便说一句,我的实际代码不会使用硬编码字符串调用构造函数,而是使用以下内容:

static constexpr auto NONE = "NONE";
Foo aFoo(NONE);
Run Code Online (Sandbox Code Playgroud)

...

#include <iostream>
#include <string>

using namespace std;


struct Foo {

    explicit Foo(bool _isVisible = false): id(""), isVisible(_isVisible) {cout << "single param ctor" << endl;}
    explicit Foo(const string _id, bool _isVisible = false): id(_id), isVisible(_isVisible) {cout << "multip param ctor" << endl;}

    const string id;
    bool isVisible;
};

int main(int argc, const char * argv[]) {

    shared_ptr<Foo> sharedFoo = make_shared<Foo>("hello");
    Foo regFoo("hi");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 8

这是继承自旧版C++并最终来自C的C++的限制.

您的字符串文字转换为bool优于"用户定义"类型std::string.

您可以添加一个构造函数,而不是在调用中进行转换const char*,可能会将其委托给您现有的构造函数,该构造函数包含std::string:

explicit Foo(const char* _id, bool _isVisible = false)
   : Foo(std::string(_id), _isVisible)
{};
Run Code Online (Sandbox Code Playgroud)

这个构造函数将是"完全匹配"(或者无论如何足够接近)并且防止bool窃取风头.

或者,因为C++ 14,而不是投用std::string文字,例如"hi"s,虽然你要记住,在这是一个通用的解决方案有点"咩"调用点做到这一点.

顺便说一下,如果你真的想std::string _id按值取你的参数,那就别做吧const; 你阻止它被移动,并在成员初始化器中需要一个副本.根据典型呼叫站点的情况,以下内容可能更有意义:

explicit Foo(
   string _id,
   bool _isVisible = false
)
   : id(std::move(_id))
   , isVisible(_isVisible)
{}
Run Code Online (Sandbox Code Playgroud)

但是,如果你通常传入左值,至少接受一个const std::string&以防止一个副本.