V. Surcharge d'opérateurs

 

Supposons notre classe point, nous voulons pouvoir surdéfinir l'opérateur + afin de pouvoir faire des additions de point.

La convention adopté par C++ pour surdéfinir l'opérateur consiste à définir une fonction de nom : operator +. On y trouve le mot clé operator suivie de l'opérateur concerné par la surdéfinition. Elle dispose de deux arguments de type point et d'une valeur de retour qui est elle-même de type point. Cette fonction peut soit être une fonction indépendante et donc forcément amie pour pouvoir accédé aux données membre, ou alors une fonction membre et donc l'un des deux argument est passé implicitement.

  1. Surcharge d'opérateur avec une fonction amie :

Si nous déclarons une fonction amie, les deux arguments sont passé de la même façons. Le prototype de notre fonction sera :

point operator + (point,point);

Voici comment cette fonction sera utilisé au sein d'une classe :

class point
	{
	 int x,y;

     public:
	 point(int abs=0,int ord=0) :x(abs),y(ord){}
	 friend point operator + (point,point);

	};

point operator +(point a,point b)
	{
	 point p;
	 p.x=a.x+p.x;
	 p.y=a.y+p.y;
	 return p;
	}

Une opération comme a+b est interprété par le compilateur comme l'appel :

operator + (a,b);

Une expression comme a+b+c est évalué comme une expression habituelle en respectant l'ordre de lecture et le priorité des opérateur ce qui équivaudrai a écrire (a+b)+c, ce qui donnerai l'appel :

operator + (operator + (a,b) ,c);
  1. Surcharge d'opérateur avec une fonction membre :

Il nous serait tout à fait possible de remplacé la fonction vue au paragraphe précédent par une fonction membre de la classe point alors l'un des deux arguments serait passé implicitement a la fonction operator, l'appel se ferait comme tel :

a.operator + (b);

Le prototype d'une telle fonction serait :

point operator + (point);

Ici une notation comme a+b+c serait interprété par le compilateur par l'appel :

a.operator + (b)).operateur + (c);

ou encore pour d'autre compilateur, par l'utilisation d'une variable temporaire

t=a.operator + (b);
t.operateur + (c);

On peut détecté le choix fait par l'opérateur en faisant affiché toute les création d'objets lors du programme.

  1. Les limite de la surcharge d'opérateur :

Tous les opérateurs ne sont pas surchargables, seul les opérateur existant déjà pour les types de base sont surchargables. Voici la liste des opérateurs surchargables en C++ :

+ - * / % ^ & |
~ ! , = < > <= >=
++ -- << >> == != && ||
+= -= /= %= ^= &= |= *=
<<= >>= [ ] ( ) -> ->* new delete

Il n'est pas possible de :

 

Attention surchargé un opérateur n'affecte en rien un autre opérateur, en effet ce n'est pas parceque nous surchargeons l'opérateur + que nous avons surchargé l'opérateur ++.

  1. surcharge des opérateur d'entrées-sorties >> et << :

Nous nous somme souvent servie d'une fonction affiche() afin d'afficher les données membre d'un objets, mais nous pouvons surchargé l'opérateur de sortie afin d'afficher sur l'écran et nous pourrions aussi surchargé l'opérateur d'entrée afin de pouvoir saisir des données à l'écrans.

Les fonctions d'entrées et de sorties admette forcément comme premier argument une référence sur un flux d'entrées ou de sorties, la surcharge ne peut donc être une fonction membre.

Voici à quoi ressemblerai ces fonction :

friend ostream& opérator << (ostream& s,point a)
	{
	 s<<a.x<<" "<<a.y;
	 return s;
	}

friend istream& opérator >> (istream& i,point a)
	{
	 i>>a.x>>" ">>a.y;
	 return i;
	}
  1. L'opérateur '=' :

Nous avons vue que l'affection au même titre que le constructeur de recopie pose probléme au niveau des pointeurs, le seul moyens de résoudre se probléme et de surcharger l'opérateur =.

Dans une déclaration telle que :

b=a;

ou a et b sont deux objets de type vect, il est important de :

De plus nous voulons pouvoir traité les affectation multiple, donc la fonction doit renvoyer un objets de retour. De plus il faut prévoir que a et b ne pointe pas sur le même emplacement mémoire, il y aurait alors l'ancien emplacement mémoire de a qui ne serai plus accésible par la suite. Voici donc la fonction surchargé telle que l'on pourrai la définir :

vect vect::operator =(const vect& v)
	{
	 if(this!= &v)
	    {
	     delete adr;
	     adr = new int[nb_elm=v.nb_elm];
	     for(int i=0;i<nb_elm;i++)adr[i]=v.adr[i];
	    }
	 return *this;
	}