【问题标题】:C++ wrong constructor being called [duplicate]C ++错误的构造函数被调用[重复]
【发布时间】:2015-08-27 15:38:10
【问题描述】:

我希望下面的代码打印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");
}

【问题讨论】:

  • "bar" 不是std::string,它是const char*,并且指针可以隐式转换为bool,并且该转换必须优先于std::string( const char* ) 构造函数.
  • 第一个版本比较好,试试 new Test("foo", std::string("bar"))
  • 在一些相关的说明中,您通常不希望在 C++ 代码中经常使用 new。如果可能,最好使用堆栈变量。只是提醒一下,因为你说你已经离开一段时间了。
  • 谢谢。我正在使用 C++11,最近遇到的一些其他事情让我相信字符串文字被视为 std::string,但我猜它们只是被隐式转换并且没有竞争转换,例如ptr -> bool 一个我在这里打的。我避免使用新的,但在弄乱代码时添加了它。
  • 我遇到了同样的问题,并通过将bool 更改为int/char 解决了它,因为我真的不喜欢在调用中像@Melkon 那样记住写一个显式的字符串构造建议。

标签: c++ c++11


【解决方案1】:

用于构造Test 的参数类型是char const[4]

char const[4] 衰减为 char const*,并且必须转换为 boolstd::string const&amp; 以使函数调用明确。

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

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

鉴于此,从指针char const*bool 的转换被认为比从char const*std::string const&amp; 的转换更好。

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

【讨论】:

    【解决方案2】:

    "bar"char const [4] 类型,从它到bool 的转换是标准的转换顺序,而到std::string 的转换是用户定义的转换。前者总是比后者更受欢迎。

    来自 N3337,[conv]/1

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

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

    [conv.array]/1

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

    [conv.bool]/1

    算术、无作用域枚举、指针或指向成员类型的指针的纯右值可以转换为bool 类型的纯右值。零值、空指针值或空成员指针值转换为false; 任何其他值都将转换为true。 ...

    因此Test("foo", "bar") 导致调用Test(const string&amp;, bool) 构造函数而不是另一个。


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

    using namespace std::literals::string_literals;
    Test("foo", "bar"s);  // calls Test(const string&, const string&, bool)
    //               ^ 
    

    【讨论】:

      【解决方案3】:

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

      我之所以会这样认为,并且你调用了错误的构造函数,是因为使用字符串文字会产生一个指针,而指针可以隐式转换为布尔值。

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

      【讨论】:

      • 我启用了以下 g++ 选项,但没有警告:-pedantic -Wall -Wextra。
      • 布尔转换比转换为std::string更匹配。
      猜你喜欢
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多