2017-09-14 22 views
4

は、この非常に簡単なコードを考えてみましょう:C++の関数定義と変数宣言の不一致?

#include <memory> 

class Foo 
{ 
public: 
    Foo() {}; 
}; 

class Bar 
{ 
public: 
    Bar(const std::shared_ptr<Foo>& foo) {} 
}; 

int main() 
{ 
    Foo* foo = new Foo; 
    Bar bar(std::shared_ptr<Foo>(foo)); 
    return 0; 
} 

Visual Studioが

warning C4930: 'Bar bar(std::shared_ptr<Foo>)': prototyped function not called (was a variable definition intended?) 

を報告して...どのようにこの行が関数定義として解釈されBar bar(std::shared_ptr<Foo>(foo));できる作成した何barオブジェクトが存在しないのはなぜ?

私はDo the parentheses after the type name make a difference with new?をチェックしてもC++: warning: C4930: prototyped function not called (was a variable definition intended?)が、私は、構文Foo()Bar()を使用していないように私の問題がここに異なっている感じ。

編集:それは正常にコンパイルされることに注意してください。

Foo* foo = new Foo; 
std::shared_ptr<Foo> fooPtr(foo); 
Bar bar(fooPtr); 
+9

C++の最も厄介な解析。 –

+0

@眠りネロクいいえ、gccはそれをコンパイルします –

+1

@RichardHodges MSVCもそうですが、それは唯一の警告です。眠りネロクが正しいです。 – Quentin

答えて

14

この問題は程度C++'s most vexing parseです。声明:

Bar bar(std::shared_ptr<Foo>(foo)); 

Barを返し、タイプstd::shared_ptr<Foo>fooと呼ばれる引数を取りbarという関数を宣言します。

最内括弧は効果がありません。あなたは以下の書かれているかのように、それは次のとおりです。

Bar bar(std::shared_ptr<Foo> foo); 

あなたはブレースの構文を使用することができます(すでにstd::shared_ptrを使用しているので)C++ 11と仮定すると代わり括弧の:

Bar bar(std::shared_ptr<Foo>{foo}); 

Barのオブジェクトbarを実際に構築します。これは、上記のステートメントは宣言として解釈できないためです。中括弧の

+3

あなたはそれが 'Bar bar(std :: shared_ptr foo); – jpo38

+2

正解ですが、Most Vexing Parseに関する説明やリンクがあり、解決策を提示した方がよいでしょう。 – aschepler

+0

可能なC++ 98またはTR1ソリューションは、目的の変数名の後に二重括弧を使用することです。パラメータ名は、たとえパラメータ宣言が1つしか含まれていなくても、あなたが指摘したように、無意味なかっこで囲むことができますが、パラメータリスト全体を囲むことはできません。従って、例えば:バーバー((std :: tr1 :: shared_ptr (foo))) ''。しかし、非常に読みにくいです... –

関連する問題