La surcharge des fonctions (overloading) est un mécanisme déclarant plusieurs fonctions avec le même nom, mais avec des signatures différentes (nombre ou type de paramètres).
Les valeurs par défaut pour les paramètres peuvent être spécifiées dans la déclaration des fonctions. Subtilité : les valeurs par défaut ne sont prises en compte que lors de la compilation de l'appel, et sont substituées par le compilateur en fonction de la signature visible.
Dans les classes, on rencontre souvent la situation :
class Printer { void print(int n, char c = '*') { /* ... */ } void print(const std::string& s) { /* ... */ } }; Printer p; p.print(5); // appellera print(int n, char c = '*'), c = '*' p.print("Hi"); // appellera print(const std::string&)
Subtilités :
void foo(int x, int y = 10); void foo(int x); foo(1); // Erreur : il n'est pas clair quelle fonction appeler
Quel est le seul endroit où il est permis de spécifier une valeur par défaut pour une fonction membre de classe ?
Réponse : La valeur par défaut pour une méthode de classe peut être spécifiée dans la déclaration de la méthode à l'intérieur de la classe (ou dans la première déclaration à l'extérieur de la classe), mais il n'est pas permis de l'indiquer à la fois dans la classe et dans l'implémentation. Sinon, une erreur de redéfinition se produira.
class X { void func(int x = 5); // Autorisé ici }; void X::func(int x) { /* ... */ } // Mais pas ici !
Histoire 1
Un incident est survenu dans un logiciel bancaire lors de la compilation : certaines fonctions surchargées avec différentes valeurs par défaut ont gêné le choix clair de la bonne, rendant les appels ambigus lors de la compilation — résultat, impossibilité de rassembler une version jusqu'à ce que des corrections manuelles soient effectuées.
Histoire 2
Dans l'équipe, un style courant était que toutes les valeurs par défaut étaient placées dans l'implémentation et non dans l'en-tête de la classe, cependant, pour certaines méthodes de classes, cela causait un désaccord entre l'interface et l'implémentation — différentes unités de traduction (TU) voyaient différents paramètres de fonction, ce qui entraînait de curieuses erreurs de compilation et d'exécution.
Histoire 3
Lors de l'extension d'une bibliothèque publique, une erreur a été commise en ajoutant une surcharge de fonction avec les mêmes paramètres, mais avec des valeurs par défaut différentes. Le compilateur a commencé à signaler des ambiguïtés lors des appels d'API, et les utilisateurs ont rencontré des appels obsolètes et des compatibilités binaires brisées.