2011-12-12 71 views
11

可能重复:
Why is it an error to use an empty set of brackets to call a constructor with no arguments?C++怪异构造

让我们有这样的代码

class Foo { 
    Foo(int) { } 
}; 

那么我们有没有结果:

int main() { 
    Foo f1 = Foo(5); // 1: OK, explicit call 
    Foo f2(5); // 2: OK, implicit call 
    Foo f3(); // 3: no error, "f3 is a non-class type Foo()", how so? 
    Foo f4(f1); // 4: OK, implicit call to default copy constructor 
    Foo f5; // 5: expected error: empty constructor missing 
} 

您能否解释一下发生了什么情况?

+13

搜索:vexing解析 – Nim

+0

@Nim:应该是一个答案。 –

+0

另请注意,示例5正在执行期望的示例3,并调用默认的构造函数。 – Joe

回答

8

Foo f3();声明称为f3的函数,返回类型为Foo

+0

啊,当然!我非常专注于构造函数...... –

12

第三行被解析为声明一个不带参数并返回Foo的函数。

2

您已经定义了一个名为f3的函数,它在3的情况下返回一个foo。在情况5中,您没有定义默认的构造函数,因此会出现错误。

5

C++有一条规则,如果一条语句可以被解释为一个函数声明,它就是这样解释的。

因此,语法Foo f3();实际上声明了一个不带参数并返回Foo的函数。通过编写Foo f3;来解决这个问题,它也会调用默认的构造函数(当然,如果有的话)。

4
  • f1调用拷贝构造函数的显式调用后,你错了这一个
  • f2是一个明确的构造函数调用//你错了这里也
  • f3声明的函数
  • f4是再次复制构造函数,如f1 //你就在这里
  • f5会调用默认的构造函数//你再次在这里
+0

'Foo f6 = 5;'会通过隐式构造函数调用吗? IIRC。 –

+0

@Douglas:是的,那是对的。 – Xeo

3

这是不是你想的是:

Foo f3(); 

你可能会认为这是默认的构造函数的显式调用,但事实并非如此。它实际上是一个名为f3的函数的声明,它不带参数并按值返回Foo

这被解析为函数声明而不是构造函数调用被称为Most Vexing Parse

+0

不,不是。 MVP是当你提供参数时,它仍然看起来像一个函数声明。这不是MVP,它只是程序员很愚蠢 –