Foo f = Foo(); //没有用于调用'Foo :: Foo(Foo)'的匹配函数......嗯?

Kyl*_*yle 12 c++ gcc constructor explicit

class Foo
{
public:
    explicit Foo() {}
    explicit Foo(Foo&) {}
};

Foo d = Foo();
Run Code Online (Sandbox Code Playgroud)

错误:没有用于调用'Foo :: Foo(Foo)'的匹配函数

我试图改变Foo(Foo&),以Foo(Foo)作为错误提示,这AFAIK不是有效的构造,果然,我得到:

错误:构造函数无效; 你可能意味着'Foo(const Foo&)'

是什么赋予了?我该如何解决这个问题?(顺便说一下,这是GCC)

CB *_*ley 13

您的复制构造函数中有两个可疑的东西.

首先,你已经复制构造函数是显式的(这是一个值得怀疑的事情),所以你(理论上)需要这样做:

Foo d( (Foo()) );
Run Code Online (Sandbox Code Playgroud)

其次,您的复制构造函数采用引用而不是const引用,这意味着您不能将它与临时使用Foo.

就个人而言,我只是explicit从复制构造函数中删除并const尽可能使其参考.

请注意,explicit默认构造函数上没有效果.[*] explicit仅对可以使用单个参数调用的构造函数产生影响.它可以防止它们用于隐式转换.对于仅采用零或仅采用两个或更多参数的构造函数,它不起作用.

[注意:两者之间可能存在差异:

Foo d;
Run Code Online (Sandbox Code Playgroud)

Foo d = Foo();
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,你有一个用户声明的默认构造函数,所以这不适用.]

编辑: [*]我只是仔细检查了这个,12.3.1 [class.conv.ctor]说你可以创建一个默认的构造函数explicit.在这种情况下,构造函数将用于执行默认初始化值初始化.老实说,我不理解这个的价值,好像你有一个用户声明的构造函数然后它是一个非POD类型,如果他们没有初始化程序,甚至非POD类型的本地对象是默认初始化的该子句所说的可以由explicit默认构造函数完成.也许有人可以指出它确实有所作为的一个极端情况但是现在我没有看到explicit对默认构造函数有什么影响.

  • 既然詹姆斯已经给出了正确答案,我可以说:因为我是一个衣橱里的粉丝. (4认同)
  • @clahey:绕过最令人烦恼的解析. (2认同)
  • @clahey:在模板和模板参数`Foo`中,构造`Foo d = Foo()`是有用的,因为如果`Foo`是原始类型,那么如果使用`Foo d`则`d`保持未初始化.相关:http://stackoverflow.com/questions/2143022/how-to-correctly-initialize-variable-of-template-type (2认同)

小智 5

您不希望将这些构造函数中的任何一个标记为显式 - 编译器需要隐式使用它们,尤其是复制构造函数.你想通过明确标记来实现什么?