Opérateurs [] et ()

Les crochets sont un opérateur binaire : l’un des arguments est la variable qui précède les crochets, l’autre celle qui se trouve entre eux. Cet opérateur est redéfinissable, ce qui permet des écritures « d’imitation de tableaux » . Par exemple, avec le type liste vu au chapitre précédent, on peut écrire :

class liste {     noeud* courant;     int nombre;     public :     // ... autres méthodes ...     friend element operator[](liste& l, int i);     };element operator[](liste& l, int i  = 0);// donne le i-ième élément de la liste après  courant{     if (!courant) return 0;     noeud *anccourant = l.courant;     l.avance(i);     element e = courant->contenu;     courant = anccourant;     return e;}

Noter la valeur par défaut pour le second argument. On peut donc écrire :

liste l;// .....element e1 = l[5], e2 = l[];

et e2 est alors la valeur courante dans la liste. Cette notation plus agréable et naturelle permet de se débarrasser de la fonction membre valeur.

Exercice 7.4

Écrire le même opérateur avec l’autre genre de liste (celle qui est en fait un tableau). Aurait-on pu écrire cet opérateur si l’on ne pouvait pas modifier la définition de la classe liste pour y insérer la déclaration friend ?

Voir solution

L’appel de fonction, qui comme on le sait se note par des parenthèses (), est un opérateur assez semblable à [], qui peut être redéfini (pas pour les fonctions, mais pour les classes). Il a un avantage déterminant sur les autres, et notamment sur [], c’est qu’on peut placer un nombre quelconque d’arguments entre les parenthèses : il s’agit donc en fait d’un opérateur « N-aire » pour toute valeur de N. Cela permet de l’utiliser pour des tableaux multidimensionnels par exemple.

Ainsi, si l’on définit une classe matrice, on peut écrire ceci :

class matrice {     double *tab;    // liste des éléments à la  suite     unsigned lgn, col;    // nb de lignes et colonnes     publi c:     // ...     double operator()(int i, int j)         { if ( (i > lgn) || (i < 1) ||                 (j > col) || (j < 1) ) return 0;           else return *(tab + (--i)*col + --j);         }     };

Nous avons ici écrit l’opérateur comme un membre, mais on aurait pu écrire une fonction amie.

Cet opérateur étant défini, il suffira donc d’écrire :

matrice M;// ...double d = M(1,5);

pour avoir le cinquième élément de la première ligne. Cette notation est plus agréable que M[1][5] qui de plus aurait nécessité une double redéfinition d’opérateur.

Noter que les deux opérateurs que nous avons définis dans ce paragraphe, et qui agissent sur des classes ayant une allure de tableau, donnent à celles-ci une grande qualité que les tableaux usuels n’ont pas : ils vérifient leurs arguments afin d’éviter des débordements des limites des tableaux. Dans nos exemples, les fonctions renvoient zéro lorsque les bornes sont dépassées, mais on pourrait aussi afficher un message d’erreur, lancer une exception, etc.

Précédent Précédent Sommaire Sommaire Suivant Suivant