空の角かっこを持つデフォルトのコンストラクター
-
05-07-2019 - |
質問
空の丸括弧(括弧)のセットが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 object();
は、コンストラクター呼び出し、または戻り値の型が MyObject でパラメーターがない object という名前の関数を宣言する関数プロトタイプです。
より冗長な構築方法を使用することもできます:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
C ++ 0xでは、これにより auto
:
auto object1 = MyObject();
auto object2 = MyObject(object1);
何度も述べたように、これは宣言です。後方互換性のためにそうなっています。 C ++の多くの分野の1つで、そのレガシーのために間抜け/一貫性のない/痛みを伴う/偽物です。
n4296 [dcl.init]から:
[注:
()
は initializer の構文では許可されていないため、X a();
はクラスXのオブジェクトの宣言ではありませんが、 引数を取らずにXを返す function の宣言。 フォーム()は、他の特定の初期化コンテキスト(5.3.4、 5.2.3、12.6.2)。
&#8212;メモの終了]
他の人が言ったように、それは関数宣言です。 C ++ 11以降では、デフォルトのコンストラクタが使用されていることを明示的に示す空の何かを表示する必要がある場合は、ブレースの初期化を使用できます。
Jedi luke{}; //default constructor