2017-05-18 124 views
2

我正在摔跤C2751編譯器錯誤,並不完全明白究竟是什麼導致它。以下很少的代碼產生錯誤:C++編譯器錯誤C2751 - 究竟是什麼導致它?

#include <iostream> 

class A { 
public: 
    A() { std::cout << "A constructed" << std::endl; }; 
    static A giveA() { return A(); } 
}; 

class B { 
public: 
    B (const A& a) { std::cout << "B constructed" << std::endl; } 
}; 


int main() { 

    B b1 = B (A::giveA()); // works 
    B b2 (B (A::giveA())); // C2751 
    B b3 (A::giveA()); // works 

} 

編譯器輸出:

consoleapplication1.cpp(21): error C2751: 'A::giveA': the name of a function parameter cannot be qualified

爲什麼我不能調用構造函數明確的b2

+1

你使用什麼編譯器?因爲gcc 5.4使用代碼構建而沒有任何問題。 – knst

+1

@knst他正在使用MSVC(請參閱C2751鏈接) – vaxquis

+1

@knst它不會與[clang](https://wandbox.org/permlink/UajAZ5zfaV8QWmZD)一起編譯。 – songyuanyao

回答

6

這是most vexing parse的問題。下鐺編譯給出了一個完整的診斷:

<source>:18:17: error: parameter declarator cannot be qualified 
    B b2 (B (A::giveA())); // C2751 
      ~~~^ 

<source>:18:10: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] 
    B b2 (B (A::giveA())); // C2751 
     ^~~~~~~~~~~~~~~~~ 

<source>:18:11: note: add a pair of parentheses to declare a variable 
    B b2 (B (A::giveA())); // C2751 
     ^
      (   ) 
1 warning and 1 error generated. 
Compiler exited with result code 1 

這樣做,因爲編譯器提示修復它:

B b2 ((B (A::giveA()))); // no error 
+0

謝謝,鏗鏘輸出非常有幫助。請問爲什麼「允許」在函數內聲明函數?我無法真正想到我想要這樣做的情況。 – spinakker

+0

想象你可能會怎麼寫:「'b2'是一個函數,它接受一個函數,該函數返回一個'B'並且接受一個函數,該函數在沒有參數的情況下返回'A :: giveA'」 –

2

該特定指令不明確;你說的方式可能是函數聲明或變量定義。

使用額外的括號應該幫助 - 它得到明確的,因爲你不能聲明/調用函數與雙括號:

B b1 = B(A::giveA()); // works 
B b2((B(A::giveA()))); // works for me 
B b3(A::giveA()); // works 

而且在這裏看到:https://en.wikipedia.org/wiki/Most_vexing_parse

+0

「沒有C-tor /方法'B(B b)',並且編譯器認爲你在​​調用它時,會讓你真的很難。編譯器_knows_你不能聲明這樣的構造函數。它不會認爲你在調用它(除非它有一些錯誤)。 – cpplearner

+0

@cpplearner感謝您發現,修復。 – vaxquis

2
B b2 (B (A::giveA())); 

即使你有B類的拷貝構造函數,你還是會得到這個因爲上面的行符合函數聲明的語法規則。括號圍繞B(A::give())解決了您的問題。

2

啊,這個問題的most vexing parse

這裏

B b2 (B (A::giveA())); // C2751 

這條線被解釋爲函數返回b2B採取了調用的函數類型B()A::giveA參數。 C2751錯誤是由無效名稱A::giveA引起的:您無法使用限定名稱作爲參數名稱。

要複製一個臨時B對象爲b2(我相信是你的意圖),你可以添加更多的括號

B b2 ((B (A::giveA()))); 

或使用大括號(只要沒有接受初始化器包含列表構造一種類型可轉換爲B

B b2 {B (A::giveA())};