构造函数转换如何工作?
#include <iostream>
using namespace::std;
class One {
public:
One() { cout<<"One"<<endl;}
};
class Two {
public:
Two(const One&) {cout<<"Two(const One&)"<<endl;}
};
void f(Two) {cout<<"f(Two)"<<endl;}
int main() {
One one;
f(one);
}
产生输出
One
Two(const One&)
f(Two)
答案 0 :(得分:3)
任何可以使用单个参数调用的构造函数都被视为implicit conversion constructor
。这包括简单的1参数情况和默认参数的使用。
在任何需要X并提供Y的上下文中考虑此转换,并且Y具有这种隐式转换的可能性。请注意,许多其他内置转换也可以作为一种混合(如调整常量,积分和fp促销,转换等)。规则是允许最多一个“用户定义”隐式转换混合
在某些情况下,这可能会非常令人惊讶,因此一般建议是制作任何此类ctors explicit
。该关键字使转换成为可能但不是隐式的:您必须使用T()语法来强制转换。
作为一个例子,考虑std::vector
有一个ctor采用size_t,设置初始大小。它是明确的 - 否则你的foo(vector<double> const& )
函数可能被错误地调用foo(42)。
答案 1 :(得分:0)
这是正确的结果。由于constructor
不是explicit
- 隐式转换有效(此处One
隐式转换为Two
)。
one
已创建,然后传递给f
转换为Two
。
答案 2 :(得分:0)
编译器必须在堆栈上创建Two
实例的副本。当您使用作为类f()
(或任何其他)的对象的参数调用One
时,编译器会查找类Two
的定义并尝试查找采用One
的构造函数(或任何其他)对象(或引用)作为参数。当找到这样的构造函数时,它使用它构造对象。它被称为隐式,因为编译器在没有干扰的情况下执行此操作。
class Foo {
public:
Foo(int number) {cout<<"Foo(int number)"<<endl;}
};
void f(Foo) {cout<<"f(Foo)"<<endl;}
int main() {
f(24);
} ///:~
输出将是: Foo(int号) F(美孚)
答案 3 :(得分:0)
Two(const One&) {cout<<"Two(const One&)"<<endl;}
构造函数的含义是,您可以随时从Two
隐式地构造One
值。当您致电f(one)
时,它需要一个Two
参数,它会被赋予One
,因此编译器会将2和2放在一起并说“我将从中创建一个临时Two
One
并完成对f()
的调用“......每个人都会很开心。乌拉!