Surcharge des opérateurs en C++

26 Sep 2019 26 Sep 2019 17284 vues ESSADDOUKI Mostafa 6 min de lecture
Introduction et syntaxe de base
1 Introduction au langage C++ 2 Entrée-sortie en C++ - cin et cout 3 Inférence de type avec le mot-clé auto en C++ 4 Classe std::string et les chaînes de caractères en C++ 5 Les structures conditionnelles (if et switch) en C++ (C++17 et C++20) 6 Les boucles en C++ (C++17 et C++20) 7 La gestion des fichiers en C++
Pointeurs et fonctions
8 Introduction aux pointeurs en C++ - Déclaration et interêts 9 Les références en C++ - déclaration et interêts 10 Les tableaux en C++ - Déclaration et interêts 11 Introduction aux fonctions en C++ 12 Passer des arguments à une fonction en C++ 13 Déclarer un paramètre const en C++ 14 Les fonctions Lambda en C++ 15 Fonctions utiles (Mathématiques et caractères) en C++
Programmation OO
16 Classes et objets en C++ 17 Spécificateurs d'accès en C++ 18 Constructeurs et destructeur d'une classe en C++ 19 Fonctions membres en C++ 20 Membres statiques d'une classe en C++ 21 Fonctions en ligne en C++ - inline 22 Fonctions et classes amies en C++ - friend 23 Surcharge des fonctions en C++ 24 Surcharge des opérateurs en C++ 25 Héritage en C++ 26 La gestion d'exceptions en C++ : déclaration, utilisation et personnalisation 27 fonctions et classes templates en C++ 28 Les nouveautés C++20 pour améliorer les templates en C++
Structures de données
29 Introduction aux structures de données 30 Les structures en C++ et la différence avec les structures en C 31 Les listes chaînées en C++ 32 Les piles en C++ 33 File d'attente en C++ 34 Arbre binaire de recherche : définition et mise en oeuvre en C++
La bibliothèque standard (STL)
35 Introduction à la bibliothèque de Template Standard STL 36 Les itérateurs en C++ - définition, déclaration et exemples 37 La classe array en C++ (bibliothèque STL) <array> 38 La classe vector de la bibliothèque STL <vector> 39 La classe deque en C++ ( Bibliothèque STL) 40 La classe list en C++ (bibliothèque STL) <list> 41 La classe stack (Pile) en C++ (bibliothèque STL) <stack> 42 La classe queue (File d'attente) en C++ (bibliothèque STL) <queue> 43 La file d'attente prioritaire (classe priority_queue) - Bibliothèque STL 44 Les ensembles en C++ (Classe set <set> - Bibliothèque STL) 45 Les dictionnaires en C++ : Classe map (Bibliothèque STL) 46 Introduction aux algorithmes de la bibliothèque STL (programmation compétitive) 47 Tri et méthodes associées en C++ - Bibliothèque STL 48 Recherche dichotomique et méthodes associées en C++ - Bibliothèque STL 49 Appliquer un prédicat ou une fonction aux éléments d'une séquence en C++ - Bibliothèque STL 50 Recherche dans une séquence et méthodes associées en C++ - Bibliothèque STL

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.

Surcharge d'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)@ est le symbole de l'opérateur.

Pourquoi 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

+-*/%^
&|~!,=
<><=>=++--
<<>>==!=&&||
+=-=/=%=^=&=
|=*=<<=>>=[]()
->->*newnew[]deletedelete[]
Opérateurs non surchargeable

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;
}
Sortie
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;
}
Sortie
p1 et p3 sont égaux
p1 est inférieur à p2
Fonctions amies pour les opérateurs

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;
}
Sortie
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.