繁体   English   中英

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

[英]Why does a function parameter call a constructor with an argument?

我有这个代码(从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);的陈述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()不将任何A对象作为参数,因此不可隐式

但是你的foo参数实际上可以用来创建一个完全匹配fn参数的B实例,你可以使用explicit关键字来防止隐式转换对象。

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

 explicit B (const A& x) {}

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

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

所以,B可以复制自己。
它不能隐式转换形式A这样的转换被声明为显式。

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

来自C ++标准

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

因此对于显式构造函数

explicit B (const A& x) {}

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

A foo;
B bar = foo;

是错的。

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

A foo;
B bar( foo );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM