2013-07-11 122 views
4

決定我有下面的代碼:奇怪的編譯器

enum nums { 
    a 
}; 

class cls { 
public: 
    cls(nums); 
}; 

void function() 
{ 
    cls(a); 
} 

當我嘗試用gcc編譯它,我得到以下錯誤:

test.cpp: In function ‘void function()’: 
test.cpp:12:10: error: no matching function for call to ‘cls::cls()’ 
test.cpp:12:10: note: candidates are: 
test.cpp:7:3: note: cls::cls(nums) 
test.cpp:7:3: note: candidate expects 1 argument, 0 provided 
test.cpp:5:7: note: cls::cls(const cls&) 
test.cpp:5:7: note: candidate expects 1 argument, 0 provided 
make: *** [test] Error 1 

如果我這個替換功能:

void function() 
{ 
    cls name(a); 
} 

然後一切正常。如果我使用帶兩個參數的構造函數,它也可以工作。如果我將「顯式」添加到構造函數,它不起作用。

我得到的gcc是以某種方式解析這個定義類型爲「cls」的名稱爲「a」的變量,但我不熟悉定義變量的這種語法。在我看來,這是一個定義類型cls的匿名臨時變量的語句,傳遞「a」是參數。

編譯gcc 4.6.3。

任何見解?

感謝, Shachar

+0

Err ...你怎麼想'cls(a);'* should * do ?! –

+0

在問題中如此說明 - 創建一個類型爲「Cls」的臨時對象。 –

回答

8

括號是可選的。因此cls (a);cls a;相同,該類型聲明cls類型的對象a並對其進行缺省初始化(因爲沒有匹配的構造函數而失敗)。

要剛剛創建在表達式的結束時到期的臨時值,則可以說,在C++ 11 cls { a };,或(cls(a));(或任何數量的更神祕構建體,如void(0), cls(a);)。

查看this answer瞭解更多創意。

+0

類似於「最令人頭痛的解析」 –

+0

@gx_:如果存在歧義,MVP和OP的問題都基於語句是函數聲明而不是表達式語句。 –

+0

這些圓括號有什麼用? – johnchen902

10

另一個最令人尷尬的解析問題的例子。該 行:

cls(a); 

聲明瞭一個名爲cls類型的a局部變量,這是(或 應該)通過調用默認構造函數初始化。 哪些不存在,哪裏出錯信息。

如果你真的想建立一個臨時對象,這將是 後立即銷燬,您可以通過 放在括號中的整個表達式消除不確定性:

(cls(a)); 

可以在括號中不會出現的定義;一個表達可以。