次のブログを読んだ後:
http://xania.org/200711/ambiguous-overloading
「コンストラクターを常に明示的に定義する必要はないのか」と自問し始めました。
だから私はこの記事を見つけた以上のものを読み始めました:
http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/
これは別の例を示し、その背後にある彼の考えも説明しています。しかし、もちろんこれはブロガーの考えの1つです。
私はあなたの何人かから聞いてうれしいです、あなたのやり方についてのあなたの考え、主題でのあなたの経験は何ですか、そしてどちらかの方法のいくつかの例はニースでしょう。
伝統的な知恵は、コンストラクターが変換を定義しない限り、コンストラクター1つのパラメーターを取る(デフォルトパラメーターを使用して明示的または効果的に)をexplicit
とマークする必要があるということです(std::string
は、const char*
から変換可能で、後者の一例です) )。暗黙の変換が実際に必要以上に人生を困難にする可能性があるという点で、あなたは自分自身で理由を理解しました。
これに対するおそらく明白な例外は、コピーコンストラクタです。または、別の方法として、ほとんどのタイプが相互に変換可能であり、コピーコンストラクターがほとんどの場合explicit
としてマークされていないことを考慮します。
他のすべての種類のコンストラクタにexplicit
をマークしても害はないように見えるかもしれませんが、私はそれに反対するでしょう。 explicit
は、C++ 03では複数の引数を取るコンストラクターに影響を与えませんが、C++ 11では影響を与えます。コードに入れるには:
struct foo {
explicit foo(int i);
foo(int i, int j);
explicit foo(int i, int j, int k);
};
foo make_foo()
{
/* Not C++11-specific: */
// Error: no conversion from int to foo
return 42;
// Okay: construction, not conversion
return foo(42);
// Okay: constructions
return foo(42, 42);
return foo(42, 42, 42);
/* C++11 specific: */
// Error: no conversion from int to foo
return { 42 };
// Not an error, not a conversion
return { 42, 42 };
// Error! Constructor is explicit
return { 42, 42, 42 };
// Not an error, direct-initialization syntax
return foo { 42, 42, 42 };
}
個人的には、foo
を返す関数では、foo { 42, 42, 42 }
を明示的に返す必要があることを不必要に冗長に感じています。 explicit
が私を何から守っているかわかりません。私は本当に{ initializers... }
構文が「与えられた初期化子からオブジェクトを構築する」ことを意味することを望んでいます、そしてexplicit
は私を何からも救いながらその方法に入ります。 ({ i }
は、コピー初期化のコンテキストでi
に要約されるため、ほとんどの場合、喜んでそれを放棄します。)
だから、単項コンストラクタにexplicit
を使う習慣を身につけようと思いますそしてそれらのみ。