web-dev-qa-db-ja.com

複数の引数を取る明示的なコンストラクター

複数の引数explicitを持つコンストラクタを作成すると、(有用な)効果がありますか?

例:

class A {
    public:
        explicit A( int b, int c ); // does explicit have any (useful) effect?
};
76
Peter G.

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
101
Sneftel

ブレースの初期化のために(たとえば配列で)つまずくでしょう

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;
}
27
StoryTeller

@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が再び関連するようになります。

そのため、アクターがexplicitであることを伝えるために、メソッドを最初に記述するときにそうするのがよいかもしれません。

23
Ami Tavory

この議論に対する私の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は、struct Barのコンストラクターがbarとして宣言されているため、explicit関数と共に初期化リストを使用できません。

6
Edgar Rokjān