2008-10-07 146 views
159

是否有任何很好的理由,一個空的圓括號(圓括號)無效在C++中調用默認的構造函數?默認構造函數與空括號

MyObject object; // ok - default ctor 
MyObject object(blah); // ok 

MyObject object(); // error 

我似乎每次都會自動輸入「()」。這是不是有很好的理由?

+0

有人應該想出一個更好的標題,但我想不出會是什麼。至少拼出「構造函數」來幫助搜索引擎。 – 2008-10-08 05:18:20

+1

這是C++對上下文敏感的另一個很好的例子。如果`blah`是一個類,問題中的示例代碼也會失敗。 – Albert 2010-08-27 21:03:10

回答

131

最棘手的解析

這與所謂的「C++的最棘手的解析」。基本上,任何可以被編譯器解釋爲聲明的東西都會被解釋爲聲明。

同樣的問題的另一實例:

std::ifstream ifs("file.txt"); 
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>()); 

v被解釋爲的函數有兩個參數的聲明。

解決方法是添加另一對括號:

std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>()); 

或者,如果你有C++ 11和列表初始化(也稱爲統一初始化)可供選擇:

std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}}; 

有了這個,它不可能被解釋爲一個函數聲明。

+0

我已經閱讀有效的STL,但我不記得看到這一點。我將不得不再次閱讀它,謝謝 – 2008-10-08 16:19:44

+6

Nitpick:你可以在函數內聲明函數。它在C中被稱爲_local functions_,並且在C++中也至少允許`extern「C」foo();`-style。 – 2009-08-08 10:20:30

50

相同的語法用於函數聲明 - 例如,函數object,不帶參數並返回MyObject

+1

謝謝 - 我不會在其他代碼中聲明一個函數。但我認爲這是合法的。 – 2008-10-07 20:36:41

10

因爲編譯器認爲它是一個不帶參數並返回MyObject實例的函數的聲明。

81

因爲它是視爲聲明的函數:

int MyFunction(); // clearly a function 
MyObject object(); // also a function declaration 
+7

我其實更喜歡這個例外的答案,它是一個更清晰的問題是什麼原因 – thecoshman 2012-10-10 13:17:56

4

我想,編譯器會不知道這樣的說法:

myObject的對象();

是一個構造函數調用或函數原型聲明名爲對象返回類型爲爲MyObject並沒有參數的功能。

4

正如多次提到的那樣,這是一個聲明。這是爲了向後兼容。 C++的許多領域之一,因其遺留問題而變得愚蠢/不一致/痛苦/虛假。

7

您還可以使用結構的更詳細的方法:

MyObject object1 = MyObject(); 
MyObject object2 = MyObject(object1); 

在C++ 0x中,這也使得auto

auto object1 = MyObject(); 
auto object2 = MyObject(object1); 
2

從n4296 [DCL。INIT]:

[注:
由於()不是由語法初始化允許的, X a();不是類X的對象的聲明,但 聲明一個功能的不帶參數並返回一個X. form()在某些其他初始化上下文中是允許的(5.3.4, 5.2.3,12.6.2)。
- 完注意事項]

0

正如其他人所說,這是一個函數聲明。由於C++ 11可以使用大括號初始化,如果您需要查看空的明確告訴您使用默認構造函數。

Jedi luke{}; //default constructor