伝統的な知恵では、1 つのパラメーター (デフォルト パラメーターを使用して明示的または効果的に) を取るexplicitコンストラクターは、変換を定義しない限り、マークする必要があります(後者の 1 つの例std::stringから変換可能)。const char*暗黙の変換が実際に生活を必要以上に困難にする可能性があるという点で、あなたはその理由を自分で理解しました。
おそらく明らかな例外は、コピー コンストラクターです。または、おそらく別の方法は、ほとんどの型がそれ自体との間で変換可能であり、そのためコピー コンストラクターはexplicitほとんどの場合マークされていないことを考慮することです。
他のすべての種類のコンストラクターをマークしても問題ないように見えるかもしれexplicitませんが、私は反対します。whileexplicitは、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明示的に return を返す必要があるのは不必要に冗長だと思いますfoo { 42, 42, 42 }。何explicitが私を守っているのかわからない。私は本当に{ initializers... }構文が「指定された初期化子からオブジェクトを構築する」ことを意味することを望んでおりexplicit、何もない状態から私を救いながらその邪魔になります。(結局のところ、コピー初期化のコンテキストで{ i }発生するためi、ほとんどの場合、喜んでそれをあきらめます。)
explicitしたがって、単項コンストラクターに使用する習慣を身につけてください。