En C++, si un constructeur peut être appelé avec un seul argument, il est par défaut considéré comme implicit. Ce constructeur peut être utilisé pour la conversion de types implicite. Pour s'en protéger, le mot-clé explicit est utilisé.
explicit interdisent les conversions implicites.L'utilisation d'explicit permet d'éviter des conversions inattendues qui peuvent se produire, par exemple, lors du passage d'un argument de type incompatible à des fonctions ou lors de l'initialisation d'une variable.
Exemple :
struct Foo { explicit Foo(int x) { /* ... */ } }; Foo a = 10; // Erreur, explicit interdit l'initialisation implicite Foo b(10); // Ok
Si explicit n'était pas utilisé, alors l'instruction Foo a = 10; aurait été autorisée et aurait pu conduire à des bogues inattendus.
Question : Tous les constructeurs déclarés avec explicit ne peuvent-ils pas être appelés lors de l'initialisation avec = ?
Réponse fréquente : Oui, explicit interdit toute initialisation avec =.
Réponse correcte : explicit interdit uniquement les conversions implicites. Avec l'initialisation directe (ClassName obj(param);), le constructeur explicit est appelé. Avec l'initialisation par copie (ClassName obj = param;) — non.
Exemple :
struct A { explicit A(int) {} }; A x = 1; // Erreur A y(1); // OK
Histoire : Dans un projet, un constructeur a été écrit sans explicit, permettant l'initialisation via des types, ce qui a entraîné des conversions automatiques inattendues des arguments des fonctions. Cela a provoqué l'apparition d'erreurs cachées et complique le débogage.
Histoire : Un développeur n'a pas mis explicit pour le constructeur du conteneur, et le constructeur par défaut a commencé à être appelé de manière inattendue lors de l'attribution ou de la transmission d'autres types. Résultat — logique de création d'objets incorrecte et comportement imprévisible.
Histoire : Un programmeur inexpérimenté a déclaré un constructeur explicit, mais a été surpris de constater que l'initialisation directe avec des parenthèses fonctionnait, pensant qu'
explicitbloquait aussi cela. Cela a conduit à ne pas utiliser de motifs sûrs pratiques et à un code superflu dans le projet.