Est-ce que créer un constructeur ayant plusieurs arguments explicita un effet (utile)?
Exemple:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Réponses:
Jusqu'au C ++ 11, oui, aucune raison d'utiliser explicitsur un constructeur multi-arg.
Cela change dans C ++ 11, en raison des listes d'initialiseurs. Fondamentalement, l'initialisation de copie (mais pas l'initialisation directe) avec une liste d'initialiseurs nécessite que le constructeur ne soit pas marqué explicit.
Exemple:
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. Je ne prendrais pas personnellement la peine de créer des constructeurs multi-arg explicit.
Vous tomberiez dessus pour l'initialisation d'accolades (par exemple dans les tableaux)
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;
}
Les excellentes réponses de @StoryTeller et @Sneftel en sont la principale raison. Cependant, à mon humble avis, cela a du sens (du moins je le fais), dans le cadre de la vérification future des modifications ultérieures du code. Considérez votre exemple:
class A {
public:
explicit A( int b, int c );
};
Ce code ne bénéficie pas directement de explicit.
Quelque temps plus tard, vous décidez d'ajouter une valeur par défaut pour c, donc cela devient ceci:
class A {
public:
A( int b, int c=0 );
};
En faisant cela, vous vous concentrez sur le cparamètre - rétrospectivement, il devrait avoir une valeur par défaut. Vous ne vous demandez pas nécessairement si Aelle-même doit être implicitement construite. Malheureusement, ce changement rend à explicitnouveau pertinent.
Donc, pour faire comprendre qu'un ctor est explicit, il pourrait être payant de le faire lors de la première écriture de la méthode.
explicitqui existe depuis toujours, et le support technique sera inondé d'appels à propos de ce changement et passera des heures à expliquer que ce explicitn'était que du bruit et que le supprimer est inoffensif. Personnellement, je ne suis pas très doué pour prédire l'avenir; il est assez difficile de décider quelle interface doit ressembler maintenant .
Voici mes cinq cents à cette discussion:
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;
}
Comme vous pouvez facilement le voir, explicitempêche d'utiliser la liste d'initialisation avec la barfonction bac struct Barcar le constructeur de est déclaré comme explicit.