Surcharge des opérateurs arithmétiques
Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 41 sur 104.
Les opérateurs arithmétiques tels que +, -, * et / sont généralement surchargés afin que les classes personnalisées se comportent comme des types numériques intégrés. Ces opérateurs renvoient généralement un nouvel objet plutôt que de modifier les opérandes.
Voici une classe Fraction avec des opérateurs arithmétiques :
class Fraction {
int numerator, denominator;
public:
Fraction(int n, int d) : numerator(n), denominator(d) {}
Fraction operator+(const Fraction& other) const {
return Fraction(
numerator * other.denominator + other.numerator * denominator,
denominator * other.denominator
);
}
Fraction operator*(const Fraction& other) const {
return Fraction(numerator * other.numerator,
denominator * other.denominator);
}
};Note que les deux opérateurs sont marqués const puisqu’ils ne modifient aucun des deux opérandes. Ils créent et renvoient une nouvelle Fraction contenant le résultat.
Pour les opérateurs d’affectation composés comme +=, le modèle est différent. Ceux-ci modifient l’opérande de gauche et renvoient une référence à celui-ci :
Fraction& operator+=(const Fraction& other) {
numerator = numerator * other.denominator + other.numerator * denominator;
denominator = denominator * other.denominator;
return *this;
}Une pratique courante consiste à implémenter l’opérateur de base en fonction de l’assignment composé, afin de réduire la duplication de code :
Fraction operator+(const Fraction& other) const {
Fraction result = *this; // Copier cet objet
result += other; // Utiliser l'affectation composée
return result;
}Cette approche garantit que les deux opérateurs restent cohérents et facilite la maintenance.
Défi
FacileConstruisons une classe Money qui gère les calculs monétaires à l’aide de la surcharge des opérateurs arithmétiques. Vous implémenterez plusieurs opérateurs arithmétiques qui vous permettront de travailler avec des valeurs monétaires aussi naturellement qu’avec des nombres ordinaires.
Vous créerez deux fichiers pour organiser votre code :
Money.h: Définissez une classeMoneyqui stocke un montant en centimes (sous forme deint) afin d’éviter les problèmes de précision des nombres à virgule flottante. Votre classe doit prendre en charge :- Un constructeur qui prend les dollars et les centimes comme entiers distincts
- Un accesseur
getDollars()qui renvoie la partie en dollars - Un accesseur
getCents()qui renvoie la partie en centimes (0-99) - Les opérateurs surchargés
+et-qui renvoient un nouvel objetMoney - Les opérateurs d’affectation composée surchargés
+=et-=qui modifient l’objet actuel et renvoient une référence vers celui-ci - Une méthode
display()qui affiche le montant au format$X.YY(toujours deux chiffres pour les centimes)
Implémentez les opérateurs de base (
+et-) en fonction des opérateurs d’affectation composée afin de réduire la duplication du code, comme indiqué dans la leçon. Tous les opérateurs arithmétiques doivent être marquésconstlorsque cela est approprié.main.cpp: Lisez quatre entiers depuis l’entrée, représentant deux montants monétaires (dollars1, cents1, dollars2, cents2 sur des lignes distinctes). Créez deux objetsMoney, puis montrez le fonctionnement de tous vos opérateurs :- Affichez
"Amount 1: "suivi du premier montant affiché - Affichez
"Amount 2: "suivi du deuxième montant affiché - Additionnez les deux montants et affichez
"Sum: "suivi du résultat - Soustrayez le deuxième montant du premier et affichez
"Difference: "suivi du résultat - Utilisez
+=pour ajouter le deuxième montant au premier, puis affichez"After +=: "suivi du premier montant modifié
- Affichez
Pour la méthode display(), utilisez std::setw(2) et std::setfill('0') de <iomanip> afin de vous assurer que les centimes sont toujours affichés avec deux chiffres (par exemple, $5.07 et non $5.7).
Convertissez les chaînes d’entrée en entiers à l’aide de std::stoi(). N’oubliez pas les gardes d’inclusion dans votre fichier d’en-tête.
Essayez vous-même
#include <iostream>
#include <string>
#include "Money.h"
using namespace std;
int main() {
// Lire les entrées pour deux montants d'argent
string line;
getline(cin, line);
int dollars1 = stoi(line);
getline(cin, line);
int cents1 = stoi(line);
getline(cin, line);
int dollars2 = stoi(line);
getline(cin, line);
int cents2 = stoi(line);
// TODO: Créer deux objets Money avec les valeurs d'entrée
// TODO: Afficher "Amount 1: " suivi du premier montant affiché
// TODO: Afficher "Amount 2: " suivi du second montant affiché
// TODO: Ajouter les deux montants et afficher "Sum: " suivi du résultat
// TODO: Soustraire le second du premier et afficher "Difference: " suivi du résultat
// TODO: Utiliser += pour ajouter le second montant au premier, puis afficher "After +=: " suivi du premier montant modifié
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesGénération et compilation en C++Fichiers d’en-tête et fichiers sourceEspaces de noms et portéeIntroduction à la POO en C++Classes et objetsLe pointeur « this »Méthodes (fonctions membres)Attributs (membres de données)Bases des constructeurs et destructeursRécapitulatif - Calculatrice simple4Propriétés de classe
Membres d’instance et statiquesAccesseurs et mutateursFonctions membres constMot-clé mutableMéthodes et variables statiquesFonctions et classes amiesRécapitulatif - Gestionnaire de compte bancaire7Héritage
Héritage de baseNiveaux d’accès de l’héritageOrdre d’appel des constructeurs et destructeursRedéfinition des méthodesFonctions virtuelles et VTableHéritage multipleHéritage virtuelRécapitulatif : hiérarchie des employés10Vue d’ensemble de la STL
Vue d’ensemble et philosophie de la STLConteneurs de la STLItérateursAlgorithmes de la STLFoncteurs et expressions lambdaRécapitulatif - fréquence des mots13Modèles de conception, partie 1
Introduction aux modèles de conceptionModèle SingletonFabrique et fabrique abstraiteModèle BuilderModèle ObserverModèle Strategy2Gestion de la mémoire
Mémoire de pile ou de tasPointeurs et référencesMémoire dynamique (new/delete)Pointeurs intelligents en C++RAII en C++Récapitulatif - Gestionnaire de tableaux dynamiques5Encapsulation
Spécificateurs d’accès en C++Spécificateurs d’accès en profondeurMasquage de l’informationStruct vs classeClasses imbriquées et internesRécapitulatif - Système de gestion des dossiers étudiants8Polymorphisme
Polymorphisme à la compilation vs à l’exécutionSurcharge de fonctionsRetour sur les fonctions virtuellesFonctions virtuelles puresClasses abstraitesConception d’interfaces en C++Conversion dynamique et RTTIRécapitulatif - Calculateur de formes3Constructeurs et destructeurs
Constructeur par défautConstructeur paramétréConstructeur de copieConstructeur de déplacementListes d’initialisation des constructeursConstructeurs déléguésApprofondissement des destructeursRègle des trois / cinq / zéroRécapitulatif - Classe String6Surcharge des opérateurs
Introduction à la surcharge des opérateursSurcharge des opérateurs arithmétiquesSurcharge des opérateurs de comparaisonOpérateurs de fluxSurcharge de l’opérateur d’affectationSurcharge des opérateurs [] et ()Opérateurs de conversion de typeRécapitulatif – Classe Matrix9Templates
Templates de fonctionsTemplates de classesSpécialisation des templatesTemplates variadiquesBases de SFINAE et des traits de typesRécapitulatif - Conteneur génériqueEntraînez-vous par vous-même : Compilateur C++ en ligne