Est-ce que créer un constructeur ayant plusieurs arguments explicit
a un effet (utile)?
Exemple:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
c++
explicit-constructor
Peter G.
la source
la source
explicit
. Je ne prendrais pas personnellement la peine de créer des constructeurs multi-argexplicit
.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; }
la source
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
c
paramètre - rétrospectivement, il devrait avoir une valeur par défaut. Vous ne vous demandez pas nécessairement siA
elle-même doit être implicitement construite. Malheureusement, ce changement rend àexplicit
nouveau 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.la source
explicit
qui existe depuis toujours, et le support technique sera inondé d'appels à propos de ce changement et passera des heures à expliquer que ceexplicit
n'é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,
explicit
empêche d'utiliser la liste d'initialisation avec labar
fonction bacstruct Bar
car le constructeur de est déclaré commeexplicit
.la source