複数の引数をexplicit持つコンストラクターを作成すると、(有用な)効果がありますか?
例:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
回答:
C ++ 11までは、ええ、explicit複数引数のコンストラクターで使用する理由はありません。
初期化リストがあるため、C ++ 11ではこれが変更されます。基本的に、初期化子リストを使用したコピー初期化(直接初期化ではない)では、コンストラクターにマークを付けない必要がありますexplicit。
例:
struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };
Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok
Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY
explicitです。私は個人的にマルチ引数コンストラクターを作成することを気にしませんexplicit。
中括弧の初期化のために(たとえば配列で)それに遭遇するでしょう
struct A {
explicit A( int b, int c ) {}
};
struct B {
B( int b, int c ) {}
};
int main() {
B b[] = {{1,2}, {3,5}}; // OK
A a1[] = {A{1,2}, A{3,4}}; // OK
A a2[] = {{1,2}, {3,4}}; // Error
return 0;
}
@StoryTellerと@Sneftelによる優れた回答が主な理由です。ただし、私見では、これは理にかなっています(少なくとも私はそうします)。将来の保証の一環として、後でコードを変更します。あなたの例を考えてみましょう:
class A {
public:
explicit A( int b, int c );
};
このコードは、から直接恩恵を受けることはありませんexplicit。
しばらくして、のデフォルト値を追加することにしたcので、次のようになります。
class A {
public:
A( int b, int c=0 );
};
これを行うときは、cパラメータに焦点を合わせています。振り返ってみると、デフォルト値が必要です。Aそれ自体を暗黙的に構築する必要があるかどうかに必ずしも焦点を当てているわけではありません。残念ながら、この変更によりexplicit再び関連性が高まります。
したがって、ctorがexplicitであることを伝えるために、最初にメソッドを作成するときにそうすることはお金がかかるかもしれません。
explicitがあり、テクニカルサポートはその変更についての電話で溢れ、それは単なるノイズであり、それを取り除くことは無害であると説明するのに何時間も費やしexplicitます。個人的には、将来を予測するのはあまり得意ではありません。インターフェイスが今どのように見えるかを決めるのは十分に難しいです。
これがこの議論に対する私の5セントです:
struct Foo {
Foo(int, double) {}
};
struct Bar {
explicit Bar(int, double) {}
};
void foo(const Foo&) {}
void bar(const Bar&) {}
int main(int argc, char * argv[]) {
foo({ 42, 42.42 }); // valid
bar({ 42, 42.42 }); // invalid
return 0;
}
簡単にわかるexplicitようにbar、のコンストラクターがstruct Barとして宣言されているため、関数と一緒に初期化子リストを使用できませんexplicit。