在下面的示例中,我的输出是"单个参数",两次。 我的问题是双重的,首先,为什么bool ctor调用而不是包含字符串的版本,第二,是否有办法在不转换调用的情况下调用字符串版本?
顺便说一句,我的实际代码并没有使用硬编码字符串调用构造函数,但是有类似的东西:
static constexpr auto NONE = "NONE";
Foo aFoo(NONE);
...
#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;
}
答案 0 :(得分:8)
这是继承自旧版C ++并最终来自C的C ++的限制。
您的字符串文字转换为bool
优于“用户定义”类型std::string
。
您可以添加一个带const char*
的构造函数,而不是在调用中强制转换,可能会将其委托给现有的构造函数std::string
:
explicit Foo(const char* _id, bool _isVisible = false)
: Foo(std::string(_id), _isVisible)
{};
这个构造函数将是“完全匹配”(或者无论如何都足够接近),并阻止bool
窃取风头。
或者,从C ++ 14开始,代替演员使用the std::string
literal,例如"hi"s
,虽然您必须记住在呼叫站点执行此操作,这对于一般解决方案来说有点“meh”。
顺便说一句,如果你真的想要按值std::string _id
参数,请不要将其const
;你阻止它被移动,并在成员初始化器中需要一个副本。根据典型呼叫站点的情况,以下内容可能更有意义:
explicit Foo(
string _id,
bool _isVisible = false
)
: id(std::move(_id))
, isVisible(_isVisible)
{}
但是,如果您通常传入左值,至少接受const std::string&
以防止复制。
答案 1 :(得分:0)
为什么bool ctor调用而不是包含字符串的版本
因为"hi"
是一个指向char 的指针,一个字符数组被转换为指向char的指针(谢谢,Lightness Races in Orbit),所以我转换为一个数字布尔。
有一种方法可以在不转换调用的情况下调用字符串版本吗?
不是很优雅,但是......你可以传递第二个布尔参数
Foo regFoo("hi", false);
排除第一个构造函数