web-dev-qa-db-ja.com

C ++は常に明示的なコンストラクターを使用します

次のブログを読んだ後:

http://xania.org/200711/ambiguous-overloading

「コンストラクターを常に明示的に定義する必要はないのか」と自問し始めました。

だから私はこの記事を見つけた以上のものを読み始めました:

http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/

これは別の例を示し、その背後にある彼の考えも説明しています。しかし、もちろんこれはブロガーの考えの1つです。

私はあなたの何人かから聞いてうれしいです、あなたのやり方についてのあなたの考え、主題でのあなたの経験は何ですか、そしてどちらかの方法のいくつかの例はニースでしょう。

35
oopsi

伝統的な知恵は、コンストラクターが変換を定義しない限り、コンストラクター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を使う習慣を身につけようと思いますそしてそれらのみ

57
Luc Danton