0

构造函数转换如何工作?

#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)
4

4 回答 4

3

任何可以使用单个参数调用的构造函数都被视为implicit conversion constructor. 这包括简单的 1 参数情况和默认参数的使用。

在任何需要 X 并提供 Y 的上下文中都会考虑这种转换,并且 Y 具有这种隐式转换的可能性。请注意,许多其他内置转换也可以混合使用(例如调整 const-ness、integral 和 fp 提升、转换等)。规则是最多允许一个“用户定义”隐式转换在混合。

在某些情况下,这可能非常令人惊讶,因此一般建议是制作任何此类 ctors explicit。该关键字使转换成为可能,但不是隐式的:您必须使用 T() 语法来强制转换。

作为一个例子,考虑std::vector有一个 ctor 采用 size_t,设置初始大小。它是明确的——否则你的foo(vector<double> const& )函数可能会被错误地用 foo(42) 调用。

于 2013-06-20T09:33:44.037 回答
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 number) f(Foo)

于 2013-06-20T09:22:33.733 回答
0

这是正确的结果。因为constructoris not explicit- 隐式转换有效(这里One隐式转换为Two)。

one被创建,然后在传递给时f转换为Two.

于 2013-06-20T09:16:51.343 回答
0

Two(const One&) {cout<<"Two(const One&)"<<endl;}构造函数的意思是你可以Two在任何时候——隐式地——从一个One. 当你调用f(one)它时,它需要一个Two参数,它被赋予了 a One,所以编译器将 2 和 2 放在一起并说“我将从 中临时做一个TwoOne完成对f()”的调用......每个人都会很高兴。欢呼!

于 2013-06-20T09:26:14.327 回答