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 Praxis besteht darin, den grundlegenden Operator mithilfe der zusammengesetzten Zuweisung zu implementieren und dadurch Code-Duplikation 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
EinfachLass uns eine Money-Klasse erstellen, die Währungsberechnungen mithilfe der Überladung arithmetischer Operatoren durchführt. Du implementierst mehrere arithmetische Operatoren, mit denen du mit Geldbeträgen genauso natürlich arbeiten kannst wie mit regulären Zahlen.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
Money.h: Definiere eineMoney-Klasse, die einen Betrag in Cent (alsint) speichert, um Probleme mit der Genauigkeit von Gleitkommazahlen zu vermeiden. Deine Klasse sollte Folgendes unterstützen:- Einen Konstruktor, der Dollar und Cent als separate Ganzzahlen entgegennimmt
- Eine Getter-Methode
getDollars(), die den Dollaranteil zurückgibt - Eine Getter-Methode
getCents(), die den Centanteil (0-99) zurückgibt - Überladene Operatoren
+und-, die ein neuesMoney-Objekt zurückgeben - Überladene zusammengesetzte Zuweisungsoperatoren
+=und-=, die das aktuelle Objekt verändern und eine Referenz darauf zurückgeben - Eine
display()-Methode, die das Geld im Format$X.YYausgibt (immer zwei Stellen für Cent)
Implementiere die grundlegenden Operatoren (
+und-) mithilfe der zusammengesetzten Zuweisungsoperatoren, um doppelte Code-Strukturen zu vermeiden, wie in der Lektion gezeigt. Alle arithmetischen Operatoren sollten, sofern sinnvoll, alsconstgekennzeichnet 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 führe anschließend alle deine Operatoren vor:- Gib
"Amount 1: "aus, gefolgt vom ersten angezeigten Betrag - Gib
"Amount 2: "aus, gefolgt vom zweiten angezeigten Betrag - Addiere die beiden Beträge und gib
"Sum: "aus, gefolgt vom Ergebnis - Subtrahiere den zweiten Betrag vom ersten und gib
"Difference: "aus, gefolgt vom Ergebnis - Verwende
+=, um den zweiten Betrag zum ersten zu addieren, und gib anschließend"After +=: "aus, gefolgt vom veränderten ersten Betrag
- Gib
Verwende für die display()-Methode std::setw(2) und std::setfill('0') aus <iomanip>, um sicherzustellen, dass die Cent immer mit zwei Stellen 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 & QuelldateienNamespaces & GültigkeitsbereichEinführung in OOP mit C++Klassen vs. ObjekteDer „this“-ZeigerMethoden (Member-Funktionen)Attribute (Datenmember)Grundlagen zu Ctors & DtorsRückblick – Einfacher Taschenrechner4Klassenattribute
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen und -KlassenZusammenfassung – Bankkontoverwaltung7Vererbung
Grundlagen der VererbungZugriffsebenen bei der VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick – Mitarbeiterhierarchie2Speicherverwaltung
Stack- vs. Heap-SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Intelligente Zeiger in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsbezeichner in C++Zugriffsbezeichner im DetailInformationsverbergungStruct vs. KlasseVerschachtelte und innere KlassenWiederholung – Studierendenverwaltungssystem8Polymorphie
Polymorphie zur Compilezeit vs. LaufzeitFunktionsüberladungVirtuelle Funktionen erneut betrachtetRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIRückblick – Shape-Calculator3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorMove-KonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktor im DetailDrei-/Fünf-/Null-RegelZusammenfassung – String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladung der Operatoren [] und ()TypkonvertierungsoperatorenWiederholung – Matrix-Klasse9Templates
FunktionstemplatesKlassen-TemplatesTemplate-SpezialisierungVariadische TemplatesGrundlagen zu SFINAE und Type TraitsRückblick – Generischer ContainerÜbe selbstständig: Online-C++-Compiler