En pratique, il existe de nombreuses fonctions dont leffet est plus général que leur implantation courante. Par exemple, la fonction de maximum :
inline int max (int a, int b){ if (a > b) return a; else return b; }
est en réalité plus générale que cela, car on peut aussi souhaiter avoir le maximum de variables de type long
, par exemple, ou double
. Dans de nombreux langages de programmation, et en C, il faudrait écrire des versions spéciales de cette fonction, avec des noms différents, tels que maxlong
, maxdouble
, etc. En C++, il est possible de donner le même nom à toutes ces fonctions :
inline int max (int a, int b){ if (a > b) return a; else return b; } inline long max (long a, long b){ if (a > b) return a; else return b; } inline double max (double a, double b){ if (a > b) return a; else return b; }
On dit que lon a réalisé un recouvrement de fonctions. Lorsque le compilateur rencontre des appels à max
, il sélectionne la bonne fonction selon le type des arguments :
int i = 1, j = 3;i = max(i, j); // appel de max(int, int)double d1, d2;d1 = max(d1, d2); // max(double, double)
Dans certains cas, cependant, on peut se demander ce qui va se passer :
float f1, f2;f1 = max(f1, f2); // quelle fonction ?
Ici, le compilateur applique les règles standard de promotion des types ; le type float
peut être changé en double
sans perte de précision, cest donc max(double, double)
qui est appelée, et le résultat est donc correct. Cependant, si nous navions pas écrit cette fonction, le compilateur aurait protesté dans lappel précédent, en indiquant Error : Ambiguity between 'max(long, long)' and 'max(int , int)', ambiguïté entre max(long, long) et max(int, int), car il nest pas possible de faire passer une variable float
par lun des types long
ou int
sans perte de précision.
Cette règle de promotion des types nous évite décrire des fonctions pour chaque type, ce qui serait fastidieux. On aurait même pu éviter décrire une fonction max(int, int)
. Dans ce cas, tous les types entiers (char
, unsigned char
, unsigned
, int
, unsigned long
, long
) utiliseraient la version max(long, long)
, tandis que float
et double
utiliseraient max(double, double)
. Seul le type long double
ne pourrait être utilisé, sauf en précisant explicitement une transformation de type :
long double ld1, ld2;ld1 = max( (double) ld1, ld2);
Dans ce cas, le premier argument permet au compilateur de résoudre lambiguïté (il nest pas nécessaire de préciser un second changement de type) ; cependant, il y a une perte de précision, il est donc préférable décrire une nouvelle version de max
.
Signalons que le cas des fonctions ayant des références pour paramètres est différent. Supposons écrites par exemple les fonctions :
inline void echange(int& a, int& b){ int c = a; a = b; b = c; } inline void echange(long& a, long& b){ long c = a; a = b; b = c; } inline void echange(double& a, double& b){ double c = a; a = b; b = c; }
Dans ce cas, si lon écrit :
float f1, f2;echange(f1, f2); // pas de concordance
le compilateur signale à nouveau une ambiguïté car la promotion des types ne sapplique pas aux références. On peut essayer décrire :
echange( (double) f1, f2);
mais alors le compilateur prévient quil utilisera une variable temporaire pour f2
(Warning : Temporary used for parameter 'b' in call to 'echange(double, double)', variable temporaire utilisée pour le paramètre 'b' dans lappel de 'echange(double, double)'). Si vous essayez quand même, une variable temporaire est en fait utilisée pour les deux paramètres, et lappel est sans effet. En fait, une variable float
ne peut être considérée comme identique à une double
, même dans une opération aussi simple. La meilleure solution consiste donc à écrire une version de echange
pour chaque type.
Dune façon générale, deux fonctions sont considérées comme différentes si elles ont une liste darguments différente, et dans ce cas elles peuvent avoir le même nom. Par contre, si seul le type de résultat renvoyé est différent, le compilateur ne peut pas distinguer les deux fonctions et affichera un message derreur si on les utilise.
Précédent | Sommaire | Suivant |