[英]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.