En C++, la plupart des opérateurs intégrés peuvent être redéfinis pour fonctionner avec des types définis par l'utilisateur. Un opérateur surchargé est une fonction dont le nom est le mot-clé operator suivi du symbole de l'opérateur.
La surcharge d'opérateur consiste à définir un comportement personnalisé pour un opérateur existant lorsqu'il est appliqué à des objets d'une classe. La signature suit la forme :type_retour operator@(paramètres) où @ est le symbole de l'opérateur.
const TypeObjet & ?Passer un objet par référence constante évite une copie coûteuse (utile pour les grands objets) tout en garantissant que l'objet source ne sera pas modifié. C'est la convention recommandée pour les opérateurs binaires.
Opérateurs pouvant être surchargés
| + | - | * | / | % | ^ |
| & | | | ~ | ! | , | = |
| < | > | <= | >= | ++ | -- |
| << | >> | == | != | && | || |
| += | -= | /= | %= | ^= | &= |
| |= | *= | <<= | >>= | [] | () |
| -> | ->* | new | new[] | delete | delete[] |
Les opérateurs suivants ne peuvent pas être surchargés : :: (résolution de portée), .* (pointeur vers membre), . (accès membre), ?: (ternaire).
Opérateurs unaires
Les opérateurs unaires agissent sur un seul opérande. Exemples : ++, --, - (unaire), !. La version préfixe ne prend pas de paramètre ; la version postfixe prend un paramètre int fictif pour les distinguer.
Exemple n°4 — Opérateurs unaires
#include <iostream>
using namespace std;
class Point {
private:
int x, y;
public:
Point(int a, int b) : x(a), y(b) {}
void afficher() { cout << " x = " << x << " et y= " << y << endl; }
Point operator-();
Point operator++(); // préfixe
Point operator++(int); // postfixe
Point operator--();
Point operator--(int);
Point operator!();
};
Point Point::operator-() { x = -x; y = -y; return Point(x, y); }
Point Point::operator++() { return Point(++x, ++y); }
Point Point::operator++(int a) { return Point(x++, y++); }
Point Point::operator--() { return Point(--x, --y); }
Point Point::operator--(int b) { return Point(x--, y--); }
Point Point::operator!() { x = x*(-1); y = y*(-1); return Point(x, y); }
int main() {
Point p1(3, 5);
cout << "Point p1 initial"; p1.afficher();
Point p = p1++;
cout << " Incrémentation Postfixe" << endl;
cout << " p : "; p.afficher();
cout << " p1 : "; p1.afficher();
-p1; cout << "moins"; p1.afficher();
!p1; cout << "négation"; p1.afficher();
return 0;
}Point p1 initial x = 3 et y= 5 Incrémentation Postfixe p : x = 3 et y= 5 p1 : x = 4 et y= 6 moins x = -4 et y= -6 négation x = 4 et y= 6
Opérateurs binaires
Les opérateurs binaires prennent deux arguments. Ils peuvent être définis comme méthodes membres (le premier opérande est *this) ou comme fonctions amies (les deux opérandes sont explicites).
Exemple n°5 — Opérateurs arithmétiques (+, -, *, /)
Point Point::operator+(const Point &p) { return Point(x+p.x, y+p.y); }
Point Point::operator-(const Point &p) { return Point(x-p.x, y-p.y); }
Point Point::operator*(const Point &p) { return Point(x*p.x, y*p.y); }
Point Point::operator/(const Point &p) { return Point(x/p.x, y/p.y); }Opérateurs relationnels
Dans l'exemple suivant, les opérateurs ==, <, >, <=, >= sont définis en comparant la distance à l'origine des points.
Exemple n°7 — Méthodes membres
#include <iostream>
#include <math.h>
using namespace std;
class Point {
private:
int x, y;
public:
Point(int a, int b) : x(a), y(b) {}
void afficher() { cout << " x = " << x << " et y= " << y << endl; }
bool operator==(const Point &p);
bool operator<(const Point &p);
bool operator>(const Point &p);
bool operator<=(const Point &p);
bool operator>=(const Point &p);
};
bool Point::operator==(const Point &p) {
return sqrt(x*x+y*y) == sqrt(p.x*p.x+p.y*p.y);
}
bool Point::operator<=(const Point &p) {
return sqrt(x*x+y*y) <= sqrt(p.x*p.x+p.y*p.y);
}
// ... (idem pour <, >, >=)
int main() {
Point p1(3,5), p2(6,-2), p3(5,3);
if (p1 == p3) cout << "p1 et p3 sont égaux" << endl;
if (p1 <= p2) cout << "p1 est inférieur à p2" << endl;
return 0;
}p1 et p3 sont égaux p1 est inférieur à p2
Les opérateurs relationnels peuvent aussi être définis comme fonctions amies (exemple n°8), ce qui est préférable quand la symétrie des opérandes est importante, ou quand le premier opérande n'est pas un objet de la classe.
Opérateur d'indice [ ]
L'opérateur [] peut être surchargé pour créer des classes de tableau avec une vérification des bornes.
Exemple n°9 — Tableau avec vérification des limites
#include <iostream>
using namespace std;
const int TAILLE = 10;
class Tableau {
private:
int tab[TAILLE];
public:
Tableau() { for (int i = 0; i < TAILLE; i++) tab[i] = i*2; }
int &operator[](int index) {
if (index > TAILLE) {
cerr << "Index hors limites" << endl;
return tab[0];
}
return tab[index];
}
};
int main() {
Tableau A;
cout << "A[2] : " << A[2] << endl;
cout << "A[5] : " << A[5] << endl;
cout << "A[12] : " << A[12] << endl;
return 0;
}A[2] : 4 A[5] : 10 A[12] : Index hors limites 0
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.