隐式构造函数参数

Implicit constructor arguments

本文关键字:参数 构造函数      更新时间:2023-10-16

我一直认为C++中的隐式构造函数只能是一个只有一个参数的构造函数。例如:

class Foo1
{
   Foo(int); // This could be an implicit constructor
};

但是以下代码正确吗:

class Foo2
{
    Foo2(int, int=0);  // Would compiler use this as an implicit constructor?
}

我可以做到:

Foo1 obj;
...
obj = 5;

Foo2呢?

首先,任何构造函数都可以标记为explicit。它有多少争论是无关紧要的。

有了这些,您现在需要了解explicit的真正含义。这只是意味着调用构造函数的唯一方法是显式地指定类名:

struct foo
{
    foo(int){}
    explicit foo(double){}
};
void bar(foo){}
bar(5); // okay, calls foo(int) to construct the foo
bar(3.14); // error, cannot call foo(double) because foo was not explicitly used
bar(foo(3.14)); // okay, calls foo(double) to construct the foo

我们不显式标记多参数构造函数的原因是因为它毫无用处。给定:

struct baz
{
    baz(int, int, int);
};

除了说baz之外,你还能怎么调用那个构造函数呢?(如baz(1, 2, 3)。)†

在您的示例中,explicit是合理的,因为只能用一个参数调用该构造函数。你实际做的只是取决于你是否觉得它应该是隐含的可转换的。


†这是在忽略C++11初始值设定项列表。在C++11中,我想你可以说:

void qaz(baz) {}
qaz({1, 2, 3}); 

并设法实现了对多参数构造函数的隐式转换,但我对初始值设定项列表的了解不够,除了作为脚注之外,无法做出有意义的注释。

如果我理解你的问题,那么答案是肯定的。

更具体地说,本质上任何只能用一个参数调用的ctor都可以并且将用于隐式转换。为了防止这种情况,可以将这样的ctor标记为explicit。这同样适用于只接受一个参数的ctor,或者可以接受多个参数,但为其他参数提供默认值的ctor。

您在这里混淆了EXplicit和IMplicit。您所说的是转换构造函数。显式构造函数正好相反:一个可以而不是用于(隐式)转换的构造函数。

为了回答您的问题:是的,Foo2(int, int=0)是一个转换构造函数,它可以像obj = 5一样实现隐式转换,因为它可以用一个int参数调用。

默认构造函数也是如此:如果为第一个参数添加默认值,它将额外成为默认构造函数。

您的意思可能是隐式构造函数,而不是显式

无论如何,你不能这样做(与你认为你能做的相反):

Foo1 obj; //this line will not compile as it takes one argument!
obj = 5;

我敢肯定,在说你可以做到这一点之前,你还没有编译过你的代码。

然而,如果你是这个意思,

Foo1 obj(10); //OK now
obj = 5;

那是的,你可以。

现在Foo2怎么样?好吧,在Foo2的情况下也可以这样做:

Foo2 foo(10);
foo = 5;