French Chinese (Simplified) Dutch English German Greek Italian Japanese Korean Spanish

     

 



 

   

 

Big Tuto : Apprenez le C++

Chapitre 20 : Surcharge des opérateurs (3)

 

Tutoriel présenté par : Robert Gillard (Gondulzac)
Date de publication : 2 avril 2017
Date de révision : -

 

Retrouvez les projets complets de ce chapitre :

  

 

 

   1 – Surcharge des opérateurs d'Entrée/Sortie (E/S)

 

    Pourquoi surcharger les opérateurs d'entrées/sorties ? surprise

 

   Prenons par exemple le corrigé de l'exercice 1 (Chap18Exercice_1) dans le chapitre 19. smiley

   Dans cet exercice on demandait de décrémenter 1 objet ''unNombre'' créé à partir d'une classe Compteur et d' afficher les 20 premiers objets de 20 à 1 à l'aide de l'opérateur operator- -.

 

   Dans la fonction main() nous affichions le résultat de la décrémentation de l'objet unNombre comme ceci :

          cout << unNombre.get_Nombre() << " ";

   En effet, l'opérateur ''<<'' n'étant pas surchargé et s'appliquant lui-même à un objet, le résultat ne pouvait être obtenu qu'en utilisant une fonction membre sur cet objet, soit unNombre.get_Nombre()wink

 

   Nous allons voir que surcharger l'opérateur ''<<'' va nous permettre d'écrire directement l'instruction d'écriture de la valeur d'un objet comme ceci :

          cout << unNombre << " ";

   Ce qui est quand-même bien plus parlant et d'une écriture semblable à l'affichage de n'importe quel type de variable faisant partie du langage. wink En effet, que unNombre soit de type int, double, de type quelconque ou bien un objet, nous écrirons toujours ''cout << unNombre'' à condition de surcharger l'opérateur ''<<'' pour afficher la valeur de l'objet. angel

   Ceci étant acquis, nous passons à l'implémentation des fonctions de surcharge des opérateurs d'entrées/sorties. wink

 

 

      1.1 – Surcharge de l'opérateur ''<<'' de la classe ostream.

 

   L'opérateur ''<<'' faisant partie de la classe ostream, la déclaration d'une fonction de surcharge de cet opérateur sera pour notre classe Nombre par exemple :

ostream &operator << (ostream &out, Nombre &rhs)

   Notez bien que la définition (implémentation) d'une fonction de surcharge d'opérateur d'entrées/sorties doit se faire impérativement en dehors de la classe. En effet, les opérateurs ''<<'' et ''>>'' faisant déjà partie de leur propre classe osteam et istream, ils ne peuvent pas être des fonctions membres d'une classe que vous allez créer. wink

   Afin de rendre ces explications compréhensibles nous allons réaliser un exercice qui additionne deux objets, assigne leur somme à un troisième objet et affiche ce dernier à l'aide de l'opérateur surchargé operator<<.  

 

   Exemple : Projet 120Surcharge_13

   Fichier Surcharge_13.h  

 

//Projet 120Surcharge_13
//Surcharge de l'opérateur ostream "<<"
//Fichier Surcharge_13.h
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
#include<iostream>
 
class Nombre
{
public:
 
// Constructeurs
Nombre() { _nb = 0; }
Nombre(size_t val) { _nb = val; }
 
// Destructeur
~Nombre() {}
 
//Fonction membre d'acquisition
 
size_t get_Valeur() const { return _nb; }
 
//Fonction operator+()
Nombre operator+ (Nombre &rhs) {
return Nombre(_nb + rhs.get_Valeur());
}
 
//Fonction operator=()
Nombre operator= (Nombre &rhs)
{
_nb = rhs._nb;
return *this;
}
 
private:
//Donnée membre privée
size_t _nb;
 
};
 
inline std::ostream &operator<< (std::ostream &out, Nombre &rhs)
{
out << rhs.get_Valeur();
return out;
}
 
#endif 

 

   Dans le fichier Surcharge_13.h nous créons deux constructeurs, le premier, constructeur par défaut, initialise la variable privée _nb à zéro. Le second constructeur est un constructeur surchargé à qui on passe un entier en paramètre.

   Suivent une méthode membre d'acquisition de données et deux fonctions de surcharge des opérateurs operator+ et operator=. Jusqu'ici, rien de compliqué, tout ça a déjà été vu. wink

   Ensuite, à l'extérieur de la classe, on trouve l'implémentation de la fonction operator<<(), ou plutôt une référence à cette fonction. Nous voyons que nous lui passons une référence du flux ostream et une référence de type Nombre en paramètres.

   Et n'oubliez pas que je vous ai dit que les fonctions de surcharge des opérateurs d'entrées/sorties devaient être définies en dehors de toute classe. cool


   Fichier Surcharge_13MainFile.cpp  

 

//projet 120Surcharge_13
//Surcharge de l'opérateur "<<"
//Fichier : Surcharge_13MainFile.cpp
 
#include <iostream>
#include "Surcharge_13.h"
#include <conio.h>
 
using namespace std;
 
int main()
{
//Création de trois objets Nombre
Nombre nombreUn(20);
Nombre nombreDeux(30);
Nombre resultat;
 
cout << endl;
cout << "Creation de trois objets 'Nombre'" << endl;
cout << "resultat = " << resultat << endl;
cout << "nombreUn = " << nombreUn << endl;
cout << "nombreDeux = " << nombreDeux << endl << endl;;
 
resultat = nombreUn + nombreDeux;
 
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
 
_getch();
return 0;
}  

 

   Après avoir créé un objet à l'aide du constructeur par défaut et deux objets à partir du constructeur surchargé auxquels nous donnons les valeurs 20 et 30, portons-nous à présent à la fin de la fonction main().

   Le résultat est affiché par l'expression :

cout << resultat << endl;

   Nous devons donc renvoyer une valeur et c'est pourquoi la fonction operator<<() doit retourner la référence au flux ostream out.

   Et la console nous donne comme résultat :

 

 

 

      1.2 – Utiliser une fonction amie pour surcharger l'opérateur ''<<''

 

   Le prototype de la fonction amie de surcharge de l'opérateur ''<<'' est le même que celui de l'exemple du projet 120Surcharge_13 mis à part qu'il est précédé du mot-clé friend, soit pour notre classe Nombre :

friend std::ostream &operator<< (std::ostream &out, Nombre &rhs)

   Notez bien que nous devons déclarer cette fonction amie à l'intérieur de la classe avant de la définir à l'extérieur wink :

 

   Exemple : Projet 121Surcharge_14

   Fichier Surcharge_14.h  

 

//Projet 121Surcharge_14
//Surcharge de l'opérateur ostream "<<"
//Utilisation d'une fonction amie
//Fichier Surcharge_13.h
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
 
#include <iostream>
 
class Nombre
{
public:
 
// Constructeurs
Nombre() { _nb = 0; }
Nombre(size_t val) { _nb = val; }
 
// Destructeur
~Nombre() {}
 
//Fonction membre d'acquisition
size_t get_Valeur() const { return _nb; }
 
//Fonction operator+()
Nombre operator+ (Nombre &rhs) {
return Nombre(_nb + rhs.get_Valeur());
}
 
//Fonction operator=()
Nombre operator= (Nombre &rhs)
{
_nb = rhs._nb;
return *this;
}
 
friend std::ostream &operator<<(std::ostream &, Nombre &);
 
 
private:
//Donnée membre privée
size_t _nb;
};
 
 
inline std::ostream &operator<< (std::ostream &out, Nombre &rhs)
{
out << rhs.get_Valeur();
return out;
}
#endif 

 

   Nous déclarons donc la fonction operator<<() précédée du mot-clé friend à l'intérieur de la classe pour que le compilateur sache que nous allons utiliser une fonction amie de la classe Nombre.

   Fichier Surcharge_14MainFile.cpp

   Le fichier Surcharge_14MainFile.cpp ainsi que le résultat dans la console étant identiques à ceux de l'exemple précédent, ceux-ci ne seront donc pas reproduits ici (vous pourrez néanmoins télécharger le projet complet en annexe wink).

 

 

      1.3 – Surcharge de l'opérateur ''>>'' de la classe istream.

 

   L'opérateur ''>>'' faisant partie de la classe istream, la déclaration d'une fonction de surcharge de cet opérateur sera pour notre classe Nombre par exemple :

istream &operator>> (istream &in, Nombre &rhs)

   ainsi que de la fonction amie :

friend std::istream &operator>> (std::istream &in, Nombre &rhs)

   Il est bien entendu que, de même qu'une fonction de surcharge de l'opérateur operator<< doit être définie en dehors de la classe, il en va de même pour la fonction operator>>()wink

   Nous allons donner un exemple de deux fonctions amies pour la surcharge des opérateurs operator<< et operator>> avec saisie de deux objets au clavier, cette fois.


   Exemple : Projet 122Surcharge_15

   Fichier Surcharge_15.h    

    

//Projet 122Surcharge_15
//Surcharge des opérateurs ostream "<<" et istream ">>"
//à l'aide de fonctions amies
//Fichier Surcharge_15.h
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
#include<iostream>
 
class Nombre
{
public:
 
// Constructeurs
Nombre() { _nb = 0; }
Nombre(size_t val) { _nb = val; }
 
// Destructeur
~Nombre() {}
 
//Fonction membre d'acquisition
 
size_t get_Valeur() const { return _nb; }
 
//Fonction operator+()
Nombre operator+ (Nombre &rhs) {
return Nombre(_nb + rhs.get_Valeur());
}
 
//Fonction operator=()
Nombre operator= (Nombre &rhs)
{
_nb = rhs._nb;
return *this;
}
 
//Déclaration des fonctions amies
friend std::ostream &operator<< (std::ostream &out, Nombre &rhs);
friend std::istream &operator>> (std::istream &in, Nombre &rhs);
 
private:
//Donnée membre privée
size_t _nb;
};
 
 
inline std::ostream &operator<< (std::ostream &out, Nombre &rhs)
{
out << rhs.get_Valeur(); // peut s'écrire aussi : out << rhs._nb;
return out;
}
 
 
inline std::istream &operator>> (std::istream &in, Nombre &rhs)
{
in >> rhs._nb;
return in;
}
 
#endif 

 

   Bien, nous déclarons donc une référence sur nos deux fonctions amies operator<<() et operator>>(). Celles-ci sont implémentées à l'extérieur de la classe. La fonction operator<<() retourne une référence à la fonction membre get_Valeur() tandis que la fonction operator>>() retourne une référence à la variable privée _nb. Remarquez que le flux étant modifié, le paramètre de droite &rhs ne peut pas être constsurprise

   Je rappelle également que les fonction amies ont accès aux variables privées de la classe et que toutes deux peuvent renvoyer rhs._nb.


   Fichier Surcharge_15MainFile.cpp 

 

//Projet 122Surcharge_15
//Surcharge des opérateurs ostream "<<" et istream ">>"
//à l'aide de fonctions amies
//Fichier Surcharge_15MainFile.cpp
 
#include "Surcharge_15.h"
#include <conio.h>
 
using namespace std;
 
int main()
{
//Création de trois objets Nombre
Nombre nombreUn;
Nombre nombreDeux;
Nombre resultat;
 
cout << endl;
cout << "Creation des objets nombreUn, nombreDeux et Resultat" << endl;
cout << "a l'aide du constructeur par defaut : " << endl << endl;
 
//On affiche la valeur des objets
cout << "nombreUn = " << nombreUn << endl;
cout << "nombreDeux = " << nombreDeux << endl;
cout << "resultat = " << resultat << endl << endl;
 
//On donne de nouvelles valeurs à nombreUn et nombreDeux
cout << "Entrez une nouvelle valeur pour l'objet nombreUn : ";
cin >> nombreUn;
cout << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreDeux : ";
cin >> nombreDeux;
cout << endl;
 
//On additionne les deux objets
resultat = nombreUn + nombreDeux;
//Et on affiche le resultat
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
 
_getch();
return 0;
} 

 

     Voilà, il n'y a rien de spécial dans ce fichier, mis-à-part que les valeurs des objets nombreUn et nombreDeux sont saisies au clavier par l'intermédiaire de la surchage de l'opérateur d'entrée istream >>wink

   Ce qui donne comme résultat dans la console :

 


    

Remarque : Jusqu'ici nous avons utilisé la surcharge des opérateurs pour réaliser de simples opérations arithmétiques sur des nombres. Il va de soit que ce n'est pas le but premier de la surcharge des opérateurs mais que nous avons utilisé ces opérations dans le but d'expliquer la surcharge d'une façon la plus simple possible.

 

   Et si vous le voulez bien, je vous propose de réaliser un premier exercice sur ce que nous venons de voir :

 

 

  Exercice 1

   Refaites l'exercice 2 du chapitre 19 (Voir le corrigé à la fin de ce chapitre) qui demandait d'écrire un programme qui affiche le résultat de l'expression suivante :

resultat = 10 + objet1 + 20 + objet2 – 15

   Pour ce nouvel exercice, vous ajouterez une fonction amie operator<<() pour l'affichage du résultat et une fonction amie operator>>() pour acquérir les valeurs des objets ''objet1'' et ''objet2'' au clavier. wink

 

 

      1.4 – Surcharge des opérateurs d'égalité/inégalité ''= ='' et ''!=''

 

   Les classes de C++ définissent l'égalité/inégalité des opérateurs de comparaison pour tester si deux objets sont équivalents ou non. Ils comparent chaque donnée membre de deux objets et traitent l'expression en conséquence.

   Leur déclaration serait pour notre classe nombre par exemple :

bool operator= = (Nombre &lhs, Nombre &rhs)

et

bool operator ! = (Nombre &lhs, Nombre &rhs)

ou

friend bool operator= = (Nombre &lhs, Nombre &rhs)

et

friend bool operator ! = (Nombre &lhs, Nombre &rhs)

   en ce qui concerne les fonctions amies.

 

   Comme vous le voyez, nous testons les paramètres left-hand side et right-hand side des fonctions, celles-ci retournant un booléen comme résultat de la comparaison.

   A titre d'exemple nous allons modifier le projet 122Surcharge_15 en y ajoutant ces deux fonctions pour comparer les objets nombreUn et nombreDeux saisis au clavier. Nous calculerons ensuite le résultat dans le cas où les deux valeurs saisies seraient égales ainsi que dans le cas où ces valeurs seraient inégales.


   Exemple : Projet 123Surcharge_16

   Fichier Surcharge_16.h  

 

//Projet 123Surcharge_16
//Surcharge des opérateurs d'égalité/inégalité "==" et "!="
//Fichier Surcharge_16.h
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
#include<iostream>
#include<string>
 
class Nombre
{
public:
// Constructeurs
Nombre() { _nb = 0; }
Nombre(size_t val) { _nb = val; }
 
// Destructeur
~Nombre() {}
 
//Fonction membre d'acquisition
size_t get_Valeur() const { return _nb; }
 
//Fonction operator+()
Nombre operator+ (Nombre &rhs) {
return Nombre(_nb + rhs.get_Valeur());
}
 
//Fonction operator=()
Nombre operator= (Nombre &rhs)
{
_nb = rhs._nb;
return *this;
}
 
//Déclaration des fonctions amies
friend std::ostream &operator<< (std::ostream &out, Nombre &rhs);
friend std::istream &operator>> (std::istream &in, Nombre &rhs);
friend bool operator==(Nombre &lhs, Nombre &rhs);
friend bool operator!=(Nombre &lhs, Nombre &rhs);
 
private:
//Donnée membre privée
size_t _nb;
 
};
 
inline std::ostream &operator<< (std::ostream &out, Nombre &rhs)
{
out << rhs.get_Valeur(); // peut s'écrire aussi : out << rhs._nb;
return out;
}
 
inline std::istream &operator>> (std::istream &in, Nombre &rhs)
{
in >> rhs._nb;
return in;
}
 
inline bool operator==(Nombre &lhs, Nombre &rhs)
{
return (lhs.get_Valeur() == rhs.get_Valeur());
}
 
inline bool operator!=(Nombre &lhs, Nombre &rhs)
{
return !(lhs.get_Valeur() == rhs.get_Valeur());
}
 
#endif 

 

   Dans ce fichier, nous avons ajouté deux fonctions amies operator= =() et operator !=() retournant un booleen. Ces fonctions ont donc pour but de comparer les valeurs des objets crées par nos constructeurs.

 

   Fichier Surcharge_16MainFile.cpp

 

//Projet 123Surcharge_16
//Surcharge des l'operateurs d'égalité/inégalité "==" et "!="
//Fichier Surcharge_16MainFine.cpp
 
#include "Surcharge_16.h"
#include <conio.h>
 
using namespace std;
 
 
int main()
{
//Création de trois objets Nombre
Nombre nombreUn;
Nombre nombreDeux;
Nombre resultat;
 
cout << endl;
cout << "Creation des objets nombreUn, nombreDeux et Resultat" << endl;
cout << "a l'aide du constructeur par defaut : " << endl << endl;
 
//On affiche la valeur des objets
cout << "nombreUn = " << nombreUn << endl;
cout << "nombreDeux = " << nombreDeux << endl;
cout << "resultat = " << resultat << endl << endl;
 
 
//On donne de nouvelles valeurs à nombreUn et nombreDeux
cout << "1er cas : On additionne les valeurs des objets si elles sont egales" << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreUn : ";
cin >> nombreUn;
cout << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreDeux : ";
cin >> nombreDeux;
cout << endl;
 
 
//Cas 1 : On additionne les valeurs si elles sont égales
 
cout << "Frappez une touche..." << endl;
_getch();
 
if (nombreUn == nombreDeux)
{
//On additionne les deux objets
resultat = nombreUn + nombreDeux;
 
//Et on affiche le resultat
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
}
 
else
cout << "Les valeurs des objets sont inegales ! " << endl << endl;
 
 
//On donne de nouvelles valeurs à nombreUn et nombreDeux
cout << endl << endl;
cout << "2eme cas : On additionne les valeurs des objets si elles sont inegales" << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreUn : ";
cin >> nombreUn;
cout << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreDeux : ";
cin >> nombreDeux;
cout << endl;
 
 
//Cas 2 : On additionne les valeurs si elles sont inégales
 
cout << "Frappez une touche..." << endl;
_getch();
 
if (nombreUn != nombreDeux)
{
//On additionne les deux objets
resultat = nombreUn + nombreDeux;
 
//Et on affiche le resultat
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
}
 
else
cout << "Les valeurs des objets sont egales ! " << endl << endl;
 
_getch();
return 0;
} 

 

   Dans ce fichier, nous additionnons le résultat des valeurs des objets entrées au clavier selon que ces valeurs sont égales ou non. Nous utilisons la surcharge des opérateurs operator= = et operator!= pour réaliser ces tests.

   Et selon les cas choisis nous obtenons divers résultats dans la console :

 

  

 

 

      1.5 – Surcharge des opérateurs de comparaison ''>'', ''>='', ''<'', ''<=''

 

   Les opérateurs de comparaison testent si un objet est plus grand qu'un autre, plus grand ou égal, plus petit ou plus petit ou égal. Les données membres de deux objets sont comparées et l'expression est traitée en conséquence. wink

 

   Leur déclaration (générale) de fonction amie serait pour notre classe nombre par exemple :

friend operator ''type_opérateur'' (const Nombre &lhs, const Nombre &rhs)

   Nous ne montrerons qu'un seul exemple reprenant les surcharges de ces différents types d'opérateurs en modifiant, par exemple, l'exemple précédent mais en enlevant les fonctions operator= =() et operator!=() afin d'épargner quelques lignes de code. wink

 

   Exemple : Projet 124Surcharge_17

   Fichier Surcharge_17.h  

 

//Projet 124Surcharge_17
//Surcharge des opérateurs de comparaison ">" et ">=", "<", "<="
//Fichier Surcharge_17.h
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
#include<iostream>
#include<string>
 
class Nombre
{
public:
 
// Constructeurs
Nombre() { _nb = 0; }
Nombre(size_t val) { _nb = val; }
 
// Destructeur
~Nombre() {}
 
//Fonction membre d'acquisition
size_t get_Valeur() const { return _nb; }
 
//Fonction operator+()
Nombre operator+ (Nombre &rhs) {
return Nombre(_nb + rhs.get_Valeur());
}
 
//Fonction operator=()
Nombre operator= (Nombre &rhs)
{
_nb = rhs._nb;
return *this;
}
 
//Fonctions de comparaison
friend bool operator>(const Nombre &lhs, const Nombre &rhs)
{
return (lhs.get_Valeur() > rhs.get_Valeur());
}
 
friend bool operator>=(const Nombre &lhs, const Nombre &rhs)
{
return (lhs.get_Valeur() >= rhs.get_Valeur());
}
 
friend bool operator<(const Nombre &lhs, const Nombre &rhs)
{
return (lhs.get_Valeur() < rhs.get_Valeur());
}
 
friend bool operator<=(const Nombre &lhs, const Nombre &rhs)
{
return (lhs.get_Valeur() <= rhs.get_Valeur());
}
 
//Déclaration des fonctions amies des opérateurs I/O
friend std::ostream &operator<< (std::ostream &out, Nombre &rhs);
friend std::istream &operator>> (std::istream &in, Nombre &rhs);
 
private:
//Donnée membre privée
size_t _nb;
};
 
 
inline
std::ostream &operator<< (std::ostream &out, Nombre &rhs)
{
out << rhs.get_Valeur(); // peut s'écrire aussi : out << rhs._nb;
return out;
}
 
 
inline
std::istream &operator>> (std::istream &in, Nombre &rhs)
{
in >> rhs._nb;
return in;
}
 
#endif 

 

   Voilà, on ajoute tout simplement quatre fonctions amies de surcharge des opérateurs pré-cités, donc rien de spécial, vous commencez à avoir l'habitude maintenant ? cheeky

 

   Fichier Surcharge_17MainFile.cpp 

 

//Projet 123Surcharge_16
//Surcharge des opérateurs d'égalité/inégalité "==" et "!="
//Fichier Surcharge_16MainFine.cpp
 
#include "Surcharge_17.h"
#include <conio.h>
 
using namespace std;
 
 
int main()
{
//Création de trois objets Nombre
Nombre nombreUn;
Nombre nombreDeux;
Nombre resultat;
 
cout << endl;
cout << "Creation des objets nombreUn, nombreDeux et Resultat" << endl;
cout << "a l'aide du constructeur par defaut : " << endl << endl;
 
//On affiche la valeur des objets
cout << "nombreUn = " << nombreUn << endl;
cout << "nombreDeux = " << nombreDeux << endl;
cout << "resultat = " << resultat << endl << endl;
 
//On donne de nouvelles valeurs à nombreUn et nombreDeux
cout << "1er cas : On additionne les valeurs des objets si la 1ere >= a la seconde" << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreUn : ";
cin >> nombreUn;
cout << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreDeux : ";
cin >> nombreDeux;
cout << endl;
 
 
//Cas 1 : On additionne les valeurs si elles sont égales
 
cout << "Frappez une touche..." << endl;
_getch();
 
if (nombreUn >= nombreDeux)
{
//On additionne le premier objet en premier
resultat = nombreUn + nombreDeux;
 
//Et on affiche le resultat
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
}
else
cout << "Le premier objet est plus petit que le premier ! " << endl << endl;
 
 
//On donne de nouvelles valeurs à nombreUn et nombreDeux
cout << endl << endl;
cout << "2eme cas : On additionne les valeurs des objets si la 1re <= a la seconde " << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreUn : ";
cin >> nombreUn;
cout << endl;
cout << "Entrez une nouvelle valeur pour l'objet nombreDeux : ";
cin >> nombreDeux;
cout << endl;
 
 
//Cas 2 : On additionne les valeurs si elles sont inégales
 
cout << "Frappez une touche..." << endl;
_getch();
 
if (nombreUn <= nombreDeux)
{
//On additionne les deux objets
resultat = nombreUn + nombreDeux;
 
//Et on affiche le resultat
cout << "resultat = nombreUn + nombreDeux" << endl;
cout << "resultat = " << resultat << endl;
}
 
else
cout << "Le premier objet est plus grand que le second ! " << endl << endl;
 
_getch();
return 0;
} 

 

     Dans ce fichier, nous additionnons le résultat des valeurs des objets entrées au clavier selon que la première valeur entrée est <= à la seconde ou dans un deuxième cas que la première valeur entrée est <= à la seconde. Nous utilisons la surcharge des opérateurs operator>= et operator<= pour réaliser ces tests.

   Et nous ne montrons qu'un des cas possibles dans la console :

 

 

   Bien, je crois que nous avons déjà fait un tour important en ce qui concerne la surcharge des opérateurs. Ceux qui parmi vous seraient intéressés par une étude plus complète de la surcharge des opérateurs, voici un lien intéressant qui pourra faire votre bonheur.

LE LANGAGE C++ MASTER 1 LA SURCHARGE D’OPÉRATEUR

 

   Allez, je crois qu'on peut passer à un petit challenge wink :

 

 

   Exercice 2 (un petit challenge – Achat d'items à un marchand)

 

   Nous avons vu auparavant qu'un objet pouvait contenir plusieurs membres et je vous propose de créer une classe ''Achat_item'' (cette classe représentera un vial ou une potion de régénération wink).

   Vous réaliserez deux transactions d'un nombre quelconque d'unités achetées et pour chaque transaction effectuée vous utiliserez la fonction operator>>() dans laquelle vous entrerez les types (nom vial), le nombre d'unités achetées ainsi que le prix unitaire (ce prix pourra être différent d'une transaction à l'autre). Les noms d'items entrés devront être impérativement identiques et vous créerez une fonction operator= =() pour comparer ceux-ci.

   Vous implémenterez d'autre part une fonction operator<<() qui permettra l'affichage d'une transaction. Les élément repris dans cet affichage seront le nom de l'item, la quantité totale achetée, le coût total et le coût unitaire moyen de chaque item acheté.

   Dans la fonction main() vous afficherez le résultat des deux transactions par l'instruction cout << item1 + item2 à la condition que le nom de chaque item soit identique.

   Vous aurez besoin d'une méthode membre pour calculer le prix moyen d'un vial et je vous laisse réfléchir à la liste des opérateurs surchargés dont vous aurez besoin pour la réalisation de cet exercice. cheeky

   Pour vous aider dans ce challenge relativement difficile angry, je vous affiche ici un exemple de résultat à obtenir dans la console (vous remarquerez que j'ai donné le type ''double'' pour le prix d'achat wink).  

 

 

   Je vous demanderai de bien vouloir être particulièrement attentifs au corrigé de cet exercice dans le chapitre 21. wink

 

 

   2 – Corrigés des exercices du chapitre 19

 

   Exercice 1 ( projet Chap19Exercice_1)

   Pour cet exercice, je vous demanderai de bien vouloir relire son énoncé dans le chapitre 19. Merci de votre compréhension. wink

 

      Fichier Chap19Ex_1.h

 

//projet Chap19Exercice_1
//Fichier : Chap19Ex_1.h
//Déclaration de la classe Nombre
//Surcharge des opérateurs binaires "+" et "-"
 
#ifndef DEF_NOMBRE
#define DEF_NOMBRE
 
typedef unsigned uint;
 
class Nombre
{
public:
 
//Constructeurs
Nombre() : _valeur(0) {}
Nombre(uint valeur) : _valeur(valeur) {}
 
//Destructeur
~Nombre() {}
 
// Fonctions membres d'accès public
uint get_Val() const { return _valeur; };
void set_Val(uint val) { _valeur = val; }
 
//Surcharge de l'opérateur de pré-incrémentation ++
const Nombre operator++()
{
++_valeur;
// Le pointeur déréférencé *this retourne l'objet incrémenté
return *this;
}
 
//Fonction operator+()
const Nombre operator+ (const Nombre &rhs) { return Nombre(_valeur + rhs.get_Val()); }
 
//Fonction operator-()
const Nombre operator- (const Nombre &rhs) { return Nombre(_valeur - rhs.get_Val()); }
 
private:
//Donnée membre privée
uint _valeur;
 
};
 
#endif 

 

     Le constructeur par défaut initialise la variable privée _valeur à zéro tandis que l'on passe une variable de type unsigned au constructeur surchargé. wink

   On définit ensuite les méthodes membres d'accès publique get_Val() et set_Val() ainsi que nos fonctions operator+() et operator-(). Cette dernière est similaire à la fonction operator+() à part que cette fois le membre de droite est soustrait de la variable privée.


      Fichier Chap19Ex_1MainFile.cpp     

 

//Projet : Chap19Exercice_1
//Fichier : Chap19Ex_1MainFile.cpp
//Addition et soustraction de deux objets
//Fonction main()
 
#include <iostream>
#include "Chap19Ex_1.h"
#include <conio.h>
 
using namespace std;
 
 
int main()
{
//Création de l'objet NombreUn à l'aide du constructeur par défaut
Nombre NombreUn;
 
//Création de deux objets à l'aide du constructeur surchargé
Nombre NombreDeux = 7;
Nombre NombreTrois = 4;
 
cout << endl;
cout << "Valeur initiale des objets a additionner : " << endl;
cout << "NombreUn = " << NombreUn.get_Val() << endl;
cout << "NombreDeux = " << NombreDeux.get_Val() << endl;
cout << "NombreTrois = " << NombreTrois.get_Val() << endl << endl;
 
cout << "On additionne les objets NombreDeux et NombreTrois : " << endl;
NombreUn = NombreDeux + NombreTrois;
cout << "NombreDeux + NombreTrois = NombreUn Soit : " << endl;
cout << NombreDeux.get_Val() << " + " << NombreTrois.get_Val() << " = " << NombreUn.get_Val() << endl << endl;
 
cout << "On incremente l'objet NombreTrois : " << endl;
++NombreTrois;
cout << "++NombreTrois = " << NombreTrois.get_Val() << endl << endl;
 
cout << "Maintenant on procede a la soustraction de NombreDeux - NombreTrois : " << endl;
cout << "NombreDeux - NombreTrois = NombreUn Soit : " << endl;
 
if (NombreDeux.get_Val() >= NombreTrois.get_Val())
{
NombreUn = NombreDeux - NombreTrois;
cout << NombreDeux.get_Val() << " - " << NombreTrois.get_Val() << " = " <<
NombreUn.get_Val() << endl << endl;
}
else
cout << "Soustraction non autorisee !" << endl;
 
_getch();
 
return 0;
} 

 

     Pour cet exercice nous n'avions pas encore implémenté la surcharge des opérateurs ''>>'' et ''<<'' donc vous voyez que nous devons utiliser une méthode membre d'accès publique get.Val() pour avoir accès aux valeurs des objets NombreUn, NombreDeux et NombreTroischeeky

   Et pour soustraire la valeur de l'objet NombreTrois de la valeur de l'objet NombreDeux, nous faisons un test sur la valeur de NombreTrois afin de ne pas avoir un résultat négatif sinon nous signalons une soustraction non autorisée. wink

 


   Exercice 2 : projet Chap19Exercice_2 (Un petit challenge)


   Pour cet exercice on demandait d'écrire un programme qui affiche le résultat (positif) de l'expression suivante :

objet3 = 10 + objet1 + 20 + objet2 – 15

   Chaque opérateur de l'expression devra être un opérateur surchargé. Comme nous n'avions pas encore vu la surcharge de l'opérateur <<, le compilateur vous refusera l'instruction ''cout << objet3''. Vous deviez utiliser à la place une fonction membre Affiche().

   Il vous fallait en outre créer un fichier de déclaration, un fichier de définition et un fichier mainFile.


      Fichier Chap19Ex_2.h 

 

//Chap19Exercice_2
//Surcharge d'opérateurs
//Fichier Chap19Ex_2.h
 
#include <iostream>
 
class Nombre
{
public:
//Constructeurs
Nombre() { _valeur = 0; }
Nombre(int val) { _valeur = val; }
 
//Fonction Affiche()
void Affiche() const;
 
//Methode membre d'acquisition
size_t geVal() { return _valeur; }
 
//Opérateurs
Nombre operator+ (Nombre &rhs); //Utilisation : ... + objet2
Nombre operator- (const size_t); //Utilisation : objet2 - 15
Nombre operator= (const Nombre rhs); //Utilisation : objet3 = ...
 
const friend Nombre operator+ (const size_t val, const Nombre &rhs); //Utilisation :
// 10 + objet1
 
friend Nombre operator+ (const Nombre &rhs, const size_t val); //Utilisation :
// objet1 + 20
 
 
private:
size_t _valeur;
 
}; 

 

   Comme nous venons de l'expliquer, la fonction membre Affiche() va nous permettre de récupérer la valeur d'objet3, n'ayant pas encore à ce moment là, parlé de la surcharge de l'opérateur ''<<''.

   Il était surtout important de voir de quels opérateurs surchargés nous avions besoin pour le calcul de l'expression :

objet3 = 10 + objet1 + 20 + objet2 – 15

   L'opérateur + est utilisé trois fois, l'opérateur une fois et l'opérateur = une fois également. Les utilisations des fonction surchargées sont notées en commentaires dans le fichier. wink

 

      Fichier Chap19Ex_2.cpp 

 

//Chapitre19Exercice_2
//Surcharge d'opérateurs
//Fichier Chap19Ex_2.cpp
 
#include "Chap19Ex_2.h"
 
using std::cout;
 
void Nombre::Affiche() const
{
cout << _valeur;
}
 
 
Nombre Nombre::operator- (const size_t val)
{
Nombre temp;
temp._valeur = _valeur - val;
return temp;
}
 
 
Nombre Nombre::operator+ (Nombre &rhs)
{
Nombre temp;
temp._valeur = _valeur + rhs._valeur;
return temp;
}
 
 
Nombre Nombre::operator= (const Nombre rhs)
{
if (this == &rhs)
return *this;
else
{
_valeur = rhs._valeur;
return *this;
}
}
 
 
const Nombre operator+ (const size_t val, const Nombre &rhs)
{
Nombre temp;
temp._valeur = val + rhs._valeur;
return temp;
}
 
 
Nombre operator+ (const Nombre &rhs, const size_t val)
{
Nombre temp;
temp._valeur = val + rhs._valeur;
return temp;
} 

 

    Les implémentations des fonctions de surcharge des opérateurs dans ce fichier de définition ayant déjà été expliquées dans les exemples de ce chapitre et des chapitres précédents, nous passons directement au code du fichier principal wink :

 

      Fichier Chap19Ex_2MainFile.cpp 

 

//Chapitre19Exercice_2
//Surcharge d'opérateurs
//Fichier Chap19Ex_2MainFile.cpp
 
#include <conio.h>
#include "Chap19Ex_2.h"
 
using namespace std;
 
 
int main()
{
Nombre objet1(25);
Nombre objet2(45);
Nombre resultat;
 
cout << endl;
cout << "Valeur de resultat = " << resultat.geVal() << endl;
 
resultat = 10 + objet1 + 20 + objet2 - 15;
 
cout << "Valeur de objet1 = " << objet1.geVal() << endl;
cout << "Valeur de objet2 = " << objet2.geVal() << endl << endl;
 
cout << "resultat = 10 + objet1 + 20 + objet2 - 15" << endl;
cout << "Valeur de resultat = ";
resultat.Affiche();
 
_getch();
return 0;
} 

 

   Le constructeur par défaut initialise l'objet ''resultat'' à 0 tandis que le constructeur surchargé initialise les objets ''objet1'' et ''objet2'' respectivement à 25 et 45.

   Nous voyons que la surcharge des opérateurs de l'expression permet le calcul de celle-ci. On accède ensuite à la valeur de l'objet ''resultat'' par l'intermédiaire de la fonction membre Affiche().

   Le résultat dans la console :

 

 

 

   Voilà, c'est tout en ce qui concerne ce chapitre. cool

   Les corrigés des exercices de ce chapitre seront présentés à la fin du chapitre 21.

      @ bientôt pour le chapitre 21 – Objets, pointeurs et références.                                                                     

            Gondulzak.  angel
 
 
 

Commentaires   

0 #1 gondulzac 02-04-2017 18:13
N'oubliez pas de laisser l'un ou l'autre commentaire si nécessaire, pour tout complément d'information dont vous pourriez avoir besoin concernant ce chapitre.
L'étude de la surcharge des opérateurs se termine ici mais le lien placé dans ce chapitre vous enverra vers une documentation complète de ce que vous pourriez apprendre sur la surcharge des opérateurs.

Connectez-vous ou inscrivez-vous pour pouvoir poster.