Creare un costruttore con più argomenti explicit
ha qualche effetto (utile)?
Esempio:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Risposte:
Fino a C ++ 11, sì, non c'è motivo di usarlo explicit
su un costruttore multi-argomento.
Ciò cambia in C ++ 11, a causa degli elenchi di inizializzatori. Fondamentalmente, l'inizializzazione della copia (ma non l'inizializzazione diretta) con un elenco di inizializzatori richiede che il costruttore non sia contrassegnato explicit
.
Esempio:
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
. Personalmente non mi preoccuperei di creare costruttori multi-argomento explicit
.
Ci si imbatte in esso per l'inizializzazione delle parentesi graffe (ad esempio negli array)
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;
}
Le ottime risposte di @StoryTeller e @Sneftel sono il motivo principale. Tuttavia, IMHO, questo ha senso (almeno lo faccio), come parte della verifica futura delle modifiche successive al codice. Considera il tuo esempio:
class A {
public:
explicit A( int b, int c );
};
Questo codice non beneficia direttamente di explicit
.
Qualche tempo dopo, decidi di aggiungere un valore predefinito per c
, quindi diventa questo:
class A {
public:
A( int b, int c=0 );
};
Quando lo fai, ti stai concentrando sul c
parametro: in retrospettiva, dovrebbe avere un valore predefinito. Non ti stai necessariamente concentrando sul fatto che se A
stesso debba essere costruito implicitamente. Sfortunatamente, questa modifica è di explicit
nuovo rilevante.
Quindi, per comunicare che un ctor è explicit
, potrebbe essere utile farlo quando si scrive per la prima volta il metodo.
explicit
che è lì da sempre e il supporto tecnico sarà inondato di chiamate su quel cambiamento e passerà ore a spiegare che explicit
era solo rumore e che rimuoverlo è innocuo. Personalmente, non sono molto bravo a predire il futuro; è già abbastanza difficile decidere come dovrebbe apparire un'interfaccia ora .
Ecco i miei cinque centesimi per questa discussione:
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;
}
Come puoi facilmente vedere, explicit
impedisce di usare la lista degli inizializzatori insieme alla bar
funzione perché il costruttore di struct Bar
è dichiarato come explicit
.