Contenu du cours
C++ Oop
C++ Oop
Surcharge d'Opérateur
La surcharge d'opérateurs est une fonctionnalité puissante dans les langages de programmation orientés objet qui vous permet de redéfinir le comportement des opérateurs pour les classes définies par l'utilisateur. En surchargeant les opérateurs, vous pouvez fournir des implémentations personnalisées pour les opérations impliquant des objets de votre classe, permettant un code plus intuitif et expressif.
La syntaxe de la surcharge d'opérateurs
La surcharge est réalisée en définissant des fonctions membres spéciales ou des fonctions amies qui implémentent le comportement souhaité pour l'opérateur. La syntaxe pour surcharger les opérateurs varie en fonction de l'opérateur que vous souhaitez surcharger. La syntaxe générale ressemble à ceci :
La syntaxe, ou plus précisément, le nombre de paramètres et le type de retour, dépend également de si vous surchargez les opérateurs en tant que fonctions membres ou fonctions amies. Considérez les deux exemples suivants :
Member
Friend
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Le tableau des opérateurs qui peuvent être surchargés
Voici un tableau répertoriant tous les opérateurs qui peuvent être surchargés. Cependant, il est important de noter que bien qu'il soit possible de surcharger ces opérateurs, il n'est absolument pas nécessaire de tous les surcharger pour vos classes.
() | function() | |
[] | array[index] | |
++ -- | ++a , a-- , etc. | |
+ - * / % | a + b , a - b , etc. | |
+= -= *= /= | a += b , a -= b , etc. | |
== != < > | a == b , a < b , etc. | |
<< >> | cout << a , cin >> a |
Nous nous concentrerons sur les opérateurs les plus couramment utilisés, y compris l'insertion et l'extraction de flux, les opérateurs arithmétiques, les opérateurs d'incrémentation et de décrémentation.
Surcharge des opérateurs d'insertion de flux
Pour surcharger les opérateurs <<
et >>
pour une classe, vous définissez généralement une fonction amie ou une fonction membre qui prend un flux de sortie (std::ostream&
) ou un flux d'entrée(std::istream&
) comme opérande gauche et un objet de votre classe comme opérande droit. Cette fonction formate ensuite les données de l'objet et les envoie au flux de sortie.
Point
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }
La surcharge des opérateurs d'insertion de flux, tels que <<
, vous permet de définir un comportement de sortie personnalisé pour les objets de vos classes lorsqu'ils sont envoyés à un flux de sortie, tel que std::cout
. Cette fonctionnalité est particulièrement utile pour améliorer la lisibilité et l'utilisabilité de votre code lors de la gestion de types de données personnalisés.
Remarque
La surcharge de l'opérateur
<<
pour le flux de sortie est plus courante que la surcharge de l'opérateur >> pour le flux d'entrée, car les opérations d'entrée avec>>
peuvent être plus sujettes à des erreurs.
Surcharge des opérateurs arithmétiques
Vous pouvez surcharger d'autres opérateurs arithmétiques (-
, *
, /
, %
) de manière similaire pour effectuer des opérations personnalisées avec vos types définis par l'utilisateur.
main
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Dans cet exemple, nous surchargeons comme une fonction membre de la classe Point. Elle prend un autre objet Point comme paramètre et retourne un nouvel objet Point qui représente la somme des deux points. Vous pouvez changer +
pour -
, *
, /
, %
et ajuster un peu la logique de l'implémentation.
Incrément et Décrément
Vous pouvez surcharger à la fois les opérateurs d'incrément et de décrément préfixés et postfixés (++
et --
) pour vos classes personnalisées. Commençons par le préfixe :
main
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Remarque
L'opérateur de décrément est surchargé de manière similaire à l'opérateur d'incrément, avec l'utilisation de l'opérateur
--
et de l'opération de soustraction.
Comme vous le voyez, il n'y a rien de difficile à surcharger l'incrément et le décrément préfixés. Cependant, cela devient plus compliqué lorsqu'il s'agit de l'opérateur postfixé. Comme vous vous en souvenez, il y a un ordre d'exécution pour l'incrément et le décrément postfixés et préfixés. Supposons que nous ayons une variable x
avec une valeur de 5
.
++Préfixe | ++x | 6 | |
Postfix++ | x++ | 5 | |
--Préfixe | --x | 4 | |
Postfix-- | x-- | 5 |
Lors de la surcharge de l'incrément et du décrément postfixés, nous devons également implémenter la fonctionnalité de l'ordre d'exécution. Cela ressemblera à quelque chose comme ceci :
main
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Remarque
Le paramètre entier est passé sans nom d'argument uniquement pour indiquer au compilateur qu'il s'agit de l'opérateur d'incrémentation postfixe qui est surchargé. Cela est nécessaire car la déclaration des opérateurs préfixe et postfixe ne diffère d'aucune autre manière.
Dans l'implémentation de l'opérateur d'incrémentation postfixe, la valeur originale de l'objet est stockée dans une variable temporaire (temp). Alors que l'objet actuel est ensuite incrémenté, la valeur retournée par l'opérateur est celle stockée dans temp. Ainsi, la variable est incrémentée, mais l'incrémentation prend effet uniquement dans l'expression suivante, car l'opérateur retourne la valeur originale.
Merci pour vos commentaires !