Un constructeur du genre X::X(Y)
permet de
convertir un objet de la classe Y
en un objet de
la classe X
, mais on ne peut pas avec un
constructeur ou une fonction membre de X
convertir
un objet de la classe X
en un objet d'une autre
classe, ou a fortiori en un objet d'un type de base.
Les fonctions de conversions permettront de réaliser
cela, une fonction de conversion est spécifiée par le
mot clé operator
, c'est obligatoirement une
fonction membre et elle ne peut avoir d'argument.
class entier1{ //... public: entier1(int i=0); //... }; class entier2{ //une autre representation des entiers? //... public: entier2(int i); operator int(); operator entier1(); //... }; //... void essai(){ entier1 a; entier2 b=10; int i=b; a=b; a=(int)b; i=12+b; };Comme les conversions réalisées par les constructeurs, les conversions définies par l'utilisateur par operator() ne peuvent s'appliquer qu'au plus une fois.
Les conversions peuvent donner lieu à certaines difficultés :
chaine::operator char*(){ return ch; }on peut alors faire:
chaine ch; //... char *ch1=ch; ch1=0;et donc ainsi accéder et modifier un membre privé. Une meilleure définition pour cette conversion serait plutôt
chaine:: operator const char*()
.+
a été surchargé pour
ent2
on a une ambiguïté:
entier2 a=4; //... a=a+3; //entier2 operator+(a,(entier2)3) // ou bien // int(a)+3 ???A moins de surcharger le
+
pour toutes les
combinaisons possibles de entier2
et int
comme argument, on ne peut supprimer cette ambiguïté.
Remarquons qu'une fonction qui n'utilise pas de conversions définies par l'utilisateur sera choisie par le compilateur de préférence à une autre qui nécessiterait une conversion:
class X{ public: X(int){}; operator int(); }; int f(X); int f(int); void essai(){ X x(2); int i; f(i); // f(int) f(x); // f(X) }