我希望下面的代码能够打印Test::Test(string,string,bool)
,但是会打印Test::Test(string,bool)
。为什么在提供两个字符串时只调用一个字符串参数的构造函数?当然一根弦不能转换成一个布尔......?我尝试添加显式关键字但它没有帮助。代码也在http://ideone.com/n3tep1。
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test(const string& str1, bool flag=false)
{
cout << "Test::Test(string,bool)" << endl;
}
Test(const string& str1, const string& str2, bool flag=false)
{
cout << "Test::Test(string,string,bool)" << endl;
}
};
int main()
{
Test* test = new Test("foo", "bar");
}
答案 0 :(得分:6)
用于构造Test
的参数类型为char const[4]
。
char const[4]
衰减到char const*
,必须转换为bool
或std::string const&
才能使函数调用明确无误。
可以使用标准转换规则将指针转换为bool
。
可以使用用户定义的转化规则将char const*
转换为std::string const&
。
鉴于此,从char const*
(指针)到bool
的转换被认为是比从char const*
到std::string const&
的转换更好的匹配。
因此,调用解析为第一个构造函数。
答案 1 :(得分:2)
"bar"
属于char const [4]
类型,从bool
转换为std::string
是标准转换序列,而转换为N T
则是用户定义的转化。前者总是优先于后者。
来自N3337, [conv] / 1
标准转化是具有内置含义的隐式转化。第4条列举了全套此类转换。 标准转换序列是一系列标准转换,顺序如下:
- 来自以下集合的零或一次转换:左值到右值转换,数组到指针转换, 和功能到指针的转换 - 来自以下集合的零或一次转换:整数促销,浮点促销,积分 转换,浮点转换,浮点积分转换,指针转换,指向成员转换的指针以及布尔转换。
- 零或一个资格转换。
在您的示例中,标准转换序列由数组到指针转换和布尔转换组成。
[conv.array] / 1
“
T
数组”或“T
未知范围数组”的左值或右值可以转换为“指向bool
的指针”的prvalue。结果是指向数组的第一个元素的指针。
[conv.bool] / 1
算术,无范围枚举,指针或指向成员类型的指针的prvalue可以转换为
false
类型的prvalue。零值,空指针值或空成员指针值将转换为true
; 任何其他值都将转换为Test("foo", "bar")
。 ...
因此Test(const string&, bool)
会导致调用using namespace std::literals::string_literals;
Test("foo", "bar"s); // calls Test(const string&, const string&, bool)
// ^
构造函数而不是另一个构造函数。
触发对其他构造函数的调用的一种方法是使用string_literals
def s = '''Sample text
--- Some text----
Another Sample text
-- Some more text ------
--Again some more text
More Sample text'''
println s.replaceAll(/(?m)^--.*$/, '')
答案 2 :(得分:0)
我希望编译器会抱怨模糊函数。
我期望的原因,以及你得到错误的构造函数的原因是,使用字符串文字导致指针,并且指针可以隐式地转换为布尔值。
在这种情况下,编译器显然认为布尔转换比转换为std::string
更好。