C++ C++;调用了错误的构造函数

C++ C++;调用了错误的构造函数,c++,c++11,C++,C++11,我希望下面的代码打印Test::Test(string,string,bool),但是它打印Test::Test(string,bool)。当提供两个字符串参数时,为什么它调用只接受一个字符串参数的构造函数?当然字符串不能转换为布尔。。。?我尝试添加显式关键字,但没有帮助。代码也位于 #包括 #包括 使用名称空间std; 课堂测试 { 公众: 测试(常量字符串和str1,bool标志=false) { cout我希望编译器会抱怨函数不明确 我期望的原因是,如果调用了错误的构造函数,那么使用字符串

我希望下面的代码打印
Test::Test(string,string,bool)
,但是它打印
Test::Test(string,bool)
。当提供两个字符串参数时,为什么它调用只接受一个字符串参数的构造函数?当然字符串不能转换为布尔。。。?我尝试添加显式关键字,但没有帮助。代码也位于

#包括
#包括
使用名称空间std;
课堂测试
{
公众:
测试(常量字符串和str1,bool标志=false)
{

cout我希望编译器会抱怨函数不明确

我期望的原因是,如果调用了错误的构造函数,那么使用字符串文字将导致指针,并且指针可以隐式转换为布尔值


在这种情况下,编译器显然认为布尔转换比转换为
std::string

更好。用于构造
测试的参数类型是
字符常量[4]

char const[4]
衰减为
char const*
,必须转换为
bool
std::string const&
,以使函数调用明确无误

可以使用标准转换规则将指针转换为
bool

可以使用用户定义的转换规则将
char const*
转换为
std::string const&

鉴于此,从指针
char const*
bool
的转换被认为比从
char const*
std::string const&
的转换更匹配

因此,调用解析为第一个构造函数。

“bar”
的类型为
char const[4]
,从它到
bool
的转换是一个标准的转换序列,而到
std::string
的转换是用户定义的转换。前者总是优于后者

从N3337开始,[conv]/1

标准转换是具有内置含义的隐式转换。第4条列举了此类转换的完整集合。标准转换序列是按以下顺序进行的标准转换序列:
-以下集合的零或一个转换:左值到右值转换,数组到指针转换, 和函数到指针的转换。
-以下集合的零或一次转换:整数提升、浮点提升、整数 转换、浮点转换、浮点整数转换、指针转换、指针到成员转换和布尔转换
-零或一个资格转换

在您的示例中,标准转换序列由数组到指针转换和布尔转换组成

[conv.array]/1

“数组的
nt
”或“数组的
T
”类型的左值或右值可以转换为“指针指向
T
”类型的PR值。结果是指向数组的第一个元素的指针

[conv.bool]/1

算术、非范围枚举、指针或指向成员类型的指针的PR值可转换为
bool
类型的PR值。零值、空指针值或空成员指针值可转换为
false
; 任何其他值都将转换为
true

因此,
Test(“foo”,“bar”)
导致调用
Test(conststring&,bool)
构造函数,而不是调用另一个构造函数


触发对另一个构造函数的调用的一种方法是使用


“bar”
不是
std::string
,它是
const char*
,指针可以隐式转换为
bool
,并且该转换必须优先于
std::string(const char*)
构造函数。第一个版本更匹配,请尝试新的测试(“foo”,std::string(“bar”))在一个有关联的注释中,通常不希望在C++代码中使用<代码>新的<代码>。如果可能的话,栈变量是首选的。只是因为你说你离开了一段时间,所以我就要做一个提示。谢谢。我使用C++ 11和最近碰到的一些其他东西使我相信字符串文字被视为STD::string,但是IG。因为它们只是被隐式转换,没有类似于我在这里遇到的ptr->bool这样的竞争转换。我避免使用新的,但在处理代码时添加了它。我遇到了同样的问题,通过将
bool
更改为
int
/
char
,解决了这个问题,因为我真的不喜欢使用o记得在调用中编写一个明确的字符串结构,如@Melkon建议的。我启用了以下g++选项,但没有警告:-pedantic-Wall-Wextra。布尔转换比转换到
std::string
更匹配。
#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");
}
using namespace std::literals::string_literals;
Test("foo", "bar"s);  // calls Test(const string&, const string&, bool)
//               ^