为什么在传递给参数时,我可以隐式地构造一个给定合适构造函数的对象?

时间:2016-03-04 07:46:44

标签: c++

在下面的示例中,为什么我只能将protected $except = [ "project_save" ]; 传递给string

printFoo()

无论出于何种原因,我都在脑海中自动确定并使用构造函数来构造对象。

为什么我不能这样做,但我可以将#include <string> #include <iostream> using namespace std; class Foo { public: Foo(const Foo &foo) : str(foo.str) {} Foo(string str) : str(str) {} string str; }; void printFoo(Foo foo) { cout << foo.str << endl; } int main() { Foo foo("qux"); printFoo(foo); // OK printFoo("qix"); // error: no matching function for call to 'printFoo' return 0; } 常量传递给接受char[n]的参数,例如?

4 个答案:

答案 0 :(得分:14)

将涉及两个隐式转换:

  1. std::string
  2. Foo
  3. C ++最多只能做一次:

    来自4次标准转换(N3337)

      

    标准转化是具有内置含义的隐式转化。   第4条列举了全套此类转换。一个标准   转换序列是一系列标准转换   以下顺序:

         

    - 来自以下集合的零次或一次转换:   左值到右值的转换,数组到指针的转换,以及   函数到指针的转换。

         

    - 来自的零或一次转换   以下集:积分促销,浮点促销,积分   转换,浮点转换,浮点积分   转换,指针转换,指向成员转换的指​​针,以及   布尔转换。

         

    - 零或一个资格转换。

    12.3转换(N3337)

      

    1类对象的类型转换可以由构造函数指定   通过转换功能。这些转换称为用户定义   转换并用于隐式类型转换(第4条),for   初始化(8.5),以及显式类型转换(5.4,5.2.9)。

         

    2用户定义的转换仅在明确无误的情况下应用   (10.2,12.3.2)。转换遵守访问控制规则(第11条)。   模糊度解决(3.4)后应用访问控制。

         

    [...]

         

    4 最多一个用户定义的   隐式应用转换(构造函数或转换函数)   为单个值。

    (强调我的)

答案 1 :(得分:7)

根据C ++标准§12.3/ 4转换[class.conv]:

  

最多一个用户定义的转换(构造函数或转换   function)隐式应用于单个值。

因此,不允许编译器连续应用两次转换。也就是说,首先是从const char[4]std::string,其次是从std::stringFoo

为此,您需要定义一个额外的构造函数:

Foo(char const *str_) : str(str_) {}

答案 2 :(得分:5)

这是因为允许编译器考虑一次转换。

要做你需要做的事情,编译器需要进行两次转换。

printFoo("qix");

// Actually needs.
printFoo(Foo(std::string("qix")));

如果你改变它,那么你传递一个字符串就可以了。

printFoo(std::string("qix"));

所有这些背后的主要原因是字符串文字的类型为char const[<size>] NOT std::string

答案 3 :(得分:1)

正如其他人所提到的,问题是需要2次转换。您可以使用s字面值将字符串文字转换为实际的std::string

printFoo("qix"s);

DEMO