Bonjour,

Je débute en C++ ainsi qu'en POO depuis quelques jours et j'apprécierai grandement votre aide.
J'aborde actuellement les classes, et en particulier l'utilisation d'opérateurs.

Je me suis imaginé un exercice dans lequel j'ai une classe nommée Monnaie qui a comme variables membres 3 valeurs numériques (livre, shilling, penny) et une string utilisable par un accesseur permettant d'afficher la valeur en texte.

Le soucis vient de l'impossibilité de passer un objet Monnaie issue d'une opération arithmétique directement dans un cout malgré la surcharge de l'opérateur << de ostream. En effet, tout fonctionne dans le programme, sauf la dernière ligne de mon main qui provoque une erreur lors de la compilation (no match for ‘operator<<’ in ‘std::operator<<):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
cout << objetMonnaie1 << " + 35 pence = " << objetMonnaie1 + 35 << endl;
Pourtant, la surcharge de operator<< fonctionne sachant que ceci passe à la compilation et au lancement :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
cout << objetMonnaie1 << endl;
C'est donc mon opérateur + qui met apparemment le boxon.
Dans la logique du programme, objetMonnaie1 + 35 renvoie pourtant bien un objet de type Monnaie, comme objetMonnaie1...

Voici le code source complet, également fourni en pièce jointe zippée :
(NB: les remarques sur l'amélioration du code pour le reste du programme sont bienvenues)

main.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include "include/Monnaie.h"
 
using namespace std;
 
int main()
{
    Monnaie monArgent(3,45,15);
    cout << "3 livres 45 shillings 15 pence = " << monArgent.str() << endl;
    monArgent.vaut(6,19,13);
    cout << "6 livres 19 shillings 13 pence = " << monArgent.str() << endl;
    cout << endl;
 
    Monnaie tonArgent(4,1);
    cout << "Ton argent : " << tonArgent.str() << endl;
    tonArgent.vaut(1);
    cout << "En fait, ton argent vaut " << tonArgent.str() << endl;
    cout << endl;
 
    Monnaie gain(20,20,20);
    Monnaie finDeMois(monArgent + gain);
    cout << "Si je travaillais, je pourrais gagner " << gain.str();
    cout << " et avoir un total de " << finDeMois.str() << endl;
 
    monArgent += tonArgent;
    cout << "C'est plus facile de te piquer ton argent, et j'ai maintenant " << monArgent.str();
    cout << " en poche" << endl;
 
    monArgent /= 2;
    cout << "Comme je dois partager à part égale avec ma femme, il ne me reste que ";
    cout << monArgent.str() << "..." << endl << endl;
 
    // utilisation de la surcharge sur l'opérateur +=
    Monnaie objetMonnaie1(1,1,1), objetMonnaie2(2,13,11);
    // - ajout d'un objet Monnaie à un autre
    cout << objetMonnaie1.str() << " + " << objetMonnaie2.str() << " = ";
    objetMonnaie1 += objetMonnaie2;
    cout << objetMonnaie1.str() << endl;
    // - ajout de 35 pence à un objet Monnaie
    cout << objetMonnaie1.str() << " + 35 pence = ";
    objetMonnaie1 += 35;
    cout << objetMonnaie1.str() << endl;
 
    // utilisation de l'opérateur de flux sortant qui réduit à 1 ligne les 3 lignes précédentes
    cout << objetMonnaie1 << " + 35 pence = " << objetMonnaie1 + 35 << endl;
 
    return 0;
}
Monnaie.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef MONNAIE_H
#define MONNAIE_H
 
#include <string>
 
class Monnaie
{
    public:
        Monnaie(int livre = 0, int shilling = 0, int penny = 0);
        ~Monnaie();
        void vaut(int livre = 0, int shilling = 0, int penny = 0);
        std::string str();
        Monnaie &operator+=(Monnaie const &autreMonnaie);
        Monnaie &operator+=(int const pennyEnPlus);
        Monnaie &operator/=(double const &diviseur);
 
    private:
        int m_livre, m_shilling, m_penny;
        std::string m_string;
};
 
Monnaie operator+(Monnaie const &monnaie1, Monnaie const &monnaie2);
Monnaie operator+(Monnaie const &monnaie, int const pennyEnPlus);
/*
* À noter que operator+ n'intervient pas sur un objet déjà existant,
* n'appartient pas à l'espace de nom Monnaie,
* et est déclaré en dehors de la classe comme une simple fonction
* basée sur operator+= qui lui appartient à la classe.
*/
std::ostream& operator<<(std::ostream &fluxSortant, Monnaie &monnaie);
 
#endif // MONNAIE_H
Monnaie.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "../include/Monnaie.h"
#include <sstream>
#include <iostream>
 
void format(int &livre, int &shilling, int &penny, std::string &chaine)
/*
* Conversion livre - shilling - penny
* 1 livre = 20 shilling
* 1 shilling = 12 penny
*
* Affectation à une string nommée chaine de
* "xx livre(s) xx shilling(s) xx penny/pence"
* représentant la valeur de Monnaie
*/
{
    // formatage numérique
    if (penny > 11)
    {
        shilling += penny/12;
        penny %= 12;
    }
    if (shilling > 19)
    {
        livre += shilling/20;
        shilling %= 20;
    }
 
    // formatage string
    // - flux de sortie pour string
    std::ostringstream fluxSortantString;
    // - écriture dans le flux
    if (livre != 0)
    {
        fluxSortantString << livre << " livre";
        if (livre > 1) {fluxSortantString << "s";}
        if (shilling != 0 || penny != 0) {fluxSortantString << " ";}
    }
    if (shilling != 0)
    {
        fluxSortantString << shilling << " shilling";
        if (shilling > 1) {fluxSortantString << "s";}
        if (penny != 0) {fluxSortantString << " ";}
    }
    if (penny != 0)
    {
        fluxSortantString << penny;
        if (penny > 1) {fluxSortantString << " pence";}
        else {fluxSortantString << " penny";}
    }
    // - récupération de la string
    chaine = fluxSortantString.str();
}
 
Monnaie::Monnaie(int livre, int shilling, int penny) : m_livre(livre), m_shilling(shilling), m_penny(penny)
{
    //constructeur
    format(m_livre, m_shilling, m_penny, m_string);
}
 
Monnaie::~Monnaie()
{
    //destructeur vide
}
 
void Monnaie::vaut(int livre, int shilling, int penny)
{
    m_livre = livre;
    m_shilling = shilling;
    m_penny = penny;
    format(m_livre, m_shilling, m_penny, m_string);
 
}
 
std::string Monnaie::str()
{
    return m_string;
}
 
Monnaie& Monnaie::operator+=(Monnaie const &autreMonnaie)
{
    // ajout des valeurs de autreMonnaie
    m_livre += autreMonnaie.m_livre;
    m_shilling += autreMonnaie.m_shilling;
    m_penny += autreMonnaie.m_penny;
    // formatage et retour
    format(m_livre, m_shilling, m_penny, m_string);
    return *this;
}
 
Monnaie& Monnaie::operator+=(int const pennyEnPlus)
{
    // ajout des pennyEnPlus
    m_penny += pennyEnPlus;
    // formatage et retour
    format(m_livre, m_shilling, m_penny, m_string);
    return *this;
}
 
Monnaie operator+(Monnaie const &monnaie1, Monnaie const &monnaie2)
/*
* operator+ n'intervient pas sur un objet déjà existant et n'appartient pas à l'espace de nom Monnaie
*/
{
    // affectation des valeurs de monnaie1 à une copie
    Monnaie copieMonnaie(monnaie1);
    // ajout des valeurs de monnaie2
    copieMonnaie += monnaie2;
    // retour (formatage effectué par l'opérateur +=)
    return copieMonnaie;
}
 
Monnaie operator+(Monnaie const &monnaie, int const pennyEnPlus)
/*
* operator+ n'intervient pas sur un objet déjà existant et n'appartient pas à l'espace de nom Monnaie
*/
{
    // affectation des valeurs de monnaie1 à une copie
    Monnaie copieMonnaie(monnaie);
    // ajout des valeurs de monnaie2
    copieMonnaie += pennyEnPlus;
    // retour (formatage effectué par l'opérateur +=)
    return copieMonnaie;
}
 
Monnaie& Monnaie::operator/=(double const &diviseur)
{
    // division des valeurs de Monnaie
    m_livre /= diviseur;
    m_shilling /= diviseur;
    m_penny /= diviseur;
    // formatage et retour
    format(m_livre, m_shilling, m_penny, m_string);
    return *this;
}
 
std::ostream& operator<<(std::ostream &fluxSortant, Monnaie &monnaie)
/*
* cout est passé en référence dans fluxSortant
* l'objet de type Monnaie est passé en référence dans la variable monnaie
*/
{
    fluxSortant << monnaie.str(); // passage dans le flux de monnaie.m_string grace à son accesseur
    return fluxSortant;
}