空の丸括弧(括弧)のセットがC++のデフォルトコンストラクターを呼び出すのに有効でない理由はありますか?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
私は毎回自動的に「()」と入力するようです。これが許可されない正当な理由はありますか?
最も厄介な解析
これは、「C++の最も厄介な解析」と呼ばれるものに関連しています。基本的に、コンパイラーが関数宣言として解釈できるものはすべて、関数宣言として解釈されます。
同じ問題の別のインスタンス:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v
は、2つのパラメーターを持つ関数の宣言として解釈されます。
回避策は、括弧の別のペアを追加することです:
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>{}};
これでは、関数宣言として解釈する方法はありません。
関数の宣言として扱われるためです:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
関数の宣言にも同じ構文が使用されます-例:関数object
、パラメーターを取らず、MyObject
を返す
コンパイラは、それが引数をとらず、MyObjectインスタンスを返す関数の宣言だと考えているためです。
より詳細な構築方法を使用することもできます。
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
C++ 0xでは、これによりauto
も許可されます。
auto object1 = MyObject();
auto object2 = MyObject(object1);
コンパイラーは、このステートメントが次のことを認識していないと思います。
MyObject object();
は、コンストラクター呼び出しまたはobjectという名前で戻り型MyObjectでパラメーターなしの関数を宣言する関数プロトタイプです。
何度も述べたように、それは宣言です。後方互換性のためにそうなっています。 C++の多くの分野の1つで、そのレガシーのために間抜け/一貫性のない/痛みを伴う/偽物です。
N4296 [dcl.init]から:
[ 注意:
_()
_はinitializerの構文では許可されていないため、X a();
はクラスXのobjectが、functionの宣言は引数(X)を返します。フォーム()は、他の特定の初期化コンテキスト(5.3.4、5.2.3、12.6.2)で許可されています。
—メモの終了]
他の人が言ったように、それは関数宣言です。 C++ 11以降では、デフォルトのコンストラクタが使用されていることを明示的に示す空のsomethingを確認する必要がある場合は、ブレースの初期化を使用できます。
Jedi luke{}; //default constructor