Arithmetische Operatorüberladung
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 41 von 104.
Arithmetische Operatoren wie +, -, * und / werden häufig überladen, damit sich benutzerdefinierte Klassen wie integrierte numerische Typen verhalten. Diese Operatoren geben typischerweise ein neues Objekt zurück, anstatt die Operanden zu verändern.
Hier ist eine Fraction-Klasse mit arithmetischen Operatoren:
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);
}
};Beachte, dass beide Operatoren als const markiert sind, da sie keinen der beiden Operanden ändern. Sie erstellen eine neue Fraction mit dem Ergebnis und geben sie zurück.
Bei zusammengesetzten Zuweisungsoperatoren wie += unterscheidet sich das Muster. Diese ändern den linken Operanden und geben eine Referenz darauf zurück:
Fraction& operator+=(const Fraction& other) {
numerator = numerator * other.denominator + other.numerator * denominator;
denominator = denominator * other.denominator;
return *this;
}Eine gängige Vorgehensweise besteht darin, den grundlegenden Operator mithilfe der zusammengesetzten Zuweisung zu implementieren und dadurch Code duplication zu reduzieren:
Fraction operator+(const Fraction& other) const {
Fraction result = *this; // Kopiere dieses Objekt
result += other; // Verwende zusammengesetzte Zuweisung
return result;
}Dieser Ansatz stellt sicher, dass beide Operatoren konsistent bleiben, und erleichtert die Wartung.
Aufgabe
EinfachErstelle eine Money-Klasse, die Währungsberechnungen mithilfe der Überladung arithmetischer Operatoren verarbeitet. Du implementierst mehrere arithmetische Operatoren, mit denen du mit Geldwerten genauso natürlich arbeiten kannst wie mit gewöhnlichen Zahlen.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
Money.h: Definiere eineMoney-Klasse, die einen amount in cents (alsint) speichert, um Probleme mit der Genauigkeit von Gleitkommazahlen zu vermeiden. Deine Klasse sollte Folgendes unterstützen:- Einen Konstruktor, der dollars und cents als separate Ganzzahlen entgegennimmt
- Einen Getter
getDollars(), der den dollar-Anteil zurückgibt - Einen Getter
getCents(), der den cents-Anteil (0-99) zurückgibt - Überladene Operatoren
+und-, die ein neuesMoney-Objekt zurückgeben - Überladene zusammengesetzte Zuweisungsoperatoren
+=und-=, die das aktuelle Objekt ändern und eine Referenz darauf zurückgeben - Eine
display()-Methode, die das Geld im Format$X.YYausgibt (für cents immer zwei Ziffern)
Implementiere die grundlegenden Operatoren (
+und-) mithilfe der zusammengesetzten Zuweisungsoperatoren, um duplication zu reduzieren, wie in der Lektion gezeigt. Alle arithmetischen Operatoren sollten, wo angemessen, alsconstmarkiert werden.main.cpp: Lies vier Ganzzahlen aus der Eingabe ein, die zwei Geldbeträge darstellen (dollars1, cents1, dollars2, cents2 in separaten Zeilen). Erstelle zweiMoney-Objekte und demonstriere anschließend alle deine Operatoren:- Gib
"Amount 1: "aus, gefolgt vom first angezeigten amount - Gib
"Amount 2: "aus, gefolgt vom zweiten angezeigten amount - Addiere die beiden amounts und gib
"Sum: "aus, gefolgt vom Ergebnis - Subtrahiere den zweiten amount vom first und gib
"Difference: "aus, gefolgt vom Ergebnis - Verwende
+=, um den zweiten amount zum first zu addieren, und gib anschließend"After +=: "aus, gefolgt vom geänderten first amount
- Gib
Verwende für die display()-Methode std::setw(2) und std::setfill('0') aus <iomanip>, damit cents immer mit zwei Ziffern angezeigt werden (z. B. $5.07 statt $5.7).
Wandle Eingabezeichenfolgen mithilfe von std::stoi() in Ganzzahlen um. Vergiss die Header-Guards in deiner Header-Datei nicht.
Probier es selbst
#include <iostream>
#include <string>
#include "Money.h"
using namespace std;
int main() {
// Eingabe für zwei Geldbeträge lesen
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: Erstelle zwei Money-Objekte mit den Eingabewerten
// TODO: Gib "Amount 1: " gefolgt vom angezeigten ersten Betrag aus
// TODO: Gib "Amount 2: " gefolgt vom angezeigten zweiten Betrag aus
// TODO: Addiere die beiden Beträge und gib "Sum: " gefolgt vom Ergebnis aus
// TODO: Subtrahiere den zweiten vom ersten und gib "Difference: " gefolgt vom Ergebnis aus
// TODO: Verwende +=, um den zweiten Betrag zum ersten zu addieren, und gib dann "After +=: " gefolgt vom geänderten ersten Betrag aus
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamensräume & GültigkeitsbereicheEinführung in OOP in C++Klassen vs. ObjekteDer 'this'-PointerMethoden (Elementfunktionen)Attribute (Datenelemente)Grundlagen zu Ctors & DtorsRückblick - Einfacher Taschenrechner4Klasseneigenschaften
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen & KlassenZusammenfassung - Bankkonto-Manager7Vererbung
Grundlagen der VererbungZugriffsstufen bei VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick - Mitarbeiter-Hierarchie2Speicherverwaltung
Stack vs. Heap SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Smart Pointers in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsspezifizierer in C++Zugriffsspezifizierer im DetailInformation HidingStruct vs. ClassVerschachtelte & innere KlassenRückblick - Studentenverwaltungssystem8Polymorphie
Kompilierzeit- vs. Laufzeit-PolymorphieFunktionsüberladungVirtuelle Funktionen – WiederholungRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIZusammenfassung – Formen-Rechner3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorVerschiebekonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktoren im DetailRule of Three / Five / ZeroZusammenfassung - String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladen der [] und () OperatorenTypumwandlungsoperatorenRückblick - Matrix-Klasse9Templates
FunktionstemplatesKlassentemplatesTemplate-SpezialisierungVariadische TemplatesSFINAE & Type Traits GrundlagenRückblick - Generische ContainerÜbe selbstständig: Online-C++-Compiler