2011-12-12 39 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,它只是程序員很愚蠢 –