为什么函数参数将带有参数的构造函数调用

Why does a function parameter call a constructor with an argument?

本文关键字:参数 函数调用 函数 为什么      更新时间:2023-10-16

我有此代码(从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) {}

这全是因为fn()的签名:

void fn (B x) {}

fn仅接受类型B的对象,并以价值传递。
那么,用A类型对象调用FN((?

的对象会发生什么情况
 A foo;
 fn (foo);  // not allowed for explicit ctor.

编译器试图找到最佳匹配函数 - 一个称为FN的函数并接收类型A。(超载分辨率(
因为没有这样的功能,因此它试图通过将对象施放到FN((接受的类型来找到下一个最佳匹配。
转换构造函数通常会完成工作:B (const A& x) {}
但是,由于它用明确的说明符标记,因此编译器无法隐式执行。

您将必须明确地施放编译器的对象才能找到匹配:

fn ((B)foo);  // Explicit conversion is allowed.

,这是对象的明确创建的结果

fn(foo); 

不是隐含的,因为fn()不会将任何对象作为参数

但是您的 foo 实际上可以使用参数来创建一个完美匹配<<strong> b b b 的实例strong> fn 参数,您可以使用 explicit keyword。

这就是您在这里所做的:

 explicit B (const A& x) {}

来自C 标准

15 在= brace-or-qual-initializer或条件的= form 中发生的初始化(6.4(,以及与参数传递中的,函数返回,抛出异常(15.1(,处理异常(15.3(和汇总成员初始化(8.6.1(,称为拷贝initialization 。[注意:复制核算可以调用移动(12.8(。

因此,对于显式构造函数

explicit B (const A& x) {}

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

的初始化
A foo;
B bar = foo;

是错误的。

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

A foo;
B bar( foo );

好... B(const B&)尽管没有明确声明,但在那里。那是因为它是编译器具有默认值的特殊功能之一:

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

所以,b可以自行复制。
它不能隐式转换形成这样的转换。

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