为什么函数参数使用参数调用构造函数?

时间:2017-06-07 11:45:08

标签: c++

我有这个代码(从cplusplus.com窃取):

// explicit:
#include <iostream>
using namespace std;

class A {};

class B {
public:
  explicit B (const A& x) {}
  B& operator= (const A& x) {return *this;}
  operator A() {return A();}
};

void fn (B x) {}

int main ()
{
  A foo;
  B bar (foo);
  bar = foo;
  foo = bar;

//  fn (foo);  // not allowed for explicit ctor.
  fn (bar);  

  return 0;
}

所以显然语句fn (foo);会调用B类中定义的构造函数,但我不知道为什么。为什么用一个参数调用一个构造函数,我的意思是在不使用引用的情况下简单地复制到函数参数?如果fn (foo);调用构造函数B (const A& x) {},那么fn (bar);不应生成错误,因为没有为类型B的参数定义构造函数,例如B (const B& x) {}?< / p>

4 个答案:

答案 0 :(得分:2)

这完全是因为super.onCreate() 的签名:

fn()

fn只接受B类型的对象,并按值传递它们 那么当用类型A的对象调用fn()时会发生什么?

void fn (B x) {}

编译器尝试查找最佳匹配函数 - 一个名为fn的函数,并接收类型A.(Overload resolution
因为没有这样的函数,所以它会尝试通过将对象转换为fn()接受的类型来找到下一个最佳匹配。
转换构造函数通常可以完成这项工作: A foo; fn (foo); // not allowed for explicit ctor.
但由于它标有explicit说明符,编译器无法隐式执行。

您必须显式转换对象以便编译器找到匹配项:

B (const A& x) {}

答案 1 :(得分:0)

这是显式创建对象的结果

fn(foo); 
由于fn()没有将任何A对象作为参数

,因此无法隐式执行

foo 参数实际上可用于创建 B 的实例,它完全匹配< strong> fn 参数,您可以使用 显式 关键字阻止隐式转换对象。

这就是你在这里做的事情:

 explicit B (const A& x) {}

答案 2 :(得分:0)

嗯...... B(const B&)虽然没有明确宣布,但是存在。那是因为它是编译器具有默认值的特殊函数之一:

B()
B(const B&)
B(B&&)
B& operator=(const B&)
B& operator==(B&&)
~B()

所以,B可以复制自己 它无法隐式转换为A,因此转换被声明为显式。

fn(B(foo))会起作用。

答案 3 :(得分:0)

来自C ++标准

15 在一个大括号或条件初始值或条件(6.4)的= form 中发生的初始化,以及与在参数传递中的函数返回抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.6.1),称为复制初始化。 [注意:复制 - 硝化可以调用移动(12.8).-结束注释]

因此对于显式构造函数

explicit B (const A& x) {}

这个初始化实际上用于初始化函数参数

A foo;
B bar = foo;

错了。

直接初始化可以与显式构造函数一起使用,如程序中所示

A foo;
B bar( foo );