我有这个代码(从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>
答案 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 );