Vergleichsoperatorüberladung
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 42 von 104.
Vergleichsoperatoren wie ==, !=, <, >, <= und >= ermöglichen es dir, Objekte deiner benutzerdefinierten Klassen zu vergleichen. Diese Operatoren geben einen bool zurück und sollten als const gekennzeichnet werden, da sie keinen der beiden Operanden verändern.
class Date {
int year, month, day;
public:
Date(int y, int m, int d) : year(y), month(m), day(d) {}
bool operator==(const Date& other) const {
return year == other.year &&
month == other.month &&
day == other.day;
}
bool operator<(const Date& other) const {
if (year != other.year) return year < other.year;
if (month != other.month) return month < other.month;
return day < other.day;
}
};Eine nützliche Technik besteht darin, andere Vergleichsoperatoren anhand derjenigen zu implementieren, die du bereits definiert hast. Sobald du == und < hast, ergeben sich die übrigen ganz natürlich:
bool operator!=(const Date& other) const {
return !(*this == other);
}
bool operator>(const Date& other) const {
return other < *this;
}
bool operator<=(const Date& other) const {
return !(other < *this);
}
bool operator>=(const Date& other) const {
return !(*this < other);
}Dieser Ansatz reduziert die Code-Duplizierung und stellt sicher, dass sich all deine Vergleichsoperatoren konsistent verhalten. Wenn du später änderst, wie Gleichheit oder „kleiner als“ funktioniert, bleiben die anderen Operatoren automatisch synchron.
Aufgabe
EinfachErstellen wir eine Version-Klasse, die Softwareversionsnummern (wie 2.1.0 oder 3.0.5) repräsentiert und alle sechs Vergleichsoperatoren unterstützt. Dies ist ein praktischer Anwendungsfall, bei dem der Vergleich von Versionen bestimmt, welche Software neuer ist – perfekt, um die Überladung von Vergleichsoperatoren zu üben.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
Version.h: Definiere eineVersion-Klasse, die drei Ganzzahlen speichert, welche die Major-, Minor- und Patch-Versionsnummern darstellen. Deine Klasse sollte Folgendes unterstützen:- Einen Konstruktor, der Major-, Minor- und Patch-Werte entgegennimmt
- Getter für jede Komponente:
getMajor(),getMinor(),getPatch()(alle const) - Alle sechs Vergleichsoperatoren:
==,!=,<,>,<=,>= - Eine
toString()-Methode, die die Version als Zeichenfolge im Format"major.minor.patch"zurückgibt
Implementiere
==und<direkt und definiere anschließend die verbleibenden vier Operatoren anhand dieser beiden. Vergleiche bei der Kleiner-als-Prüfung zuerst Major, dann Minor, falls die Majors gleich sind, und anschließend Patch, falls Major und Minor gleich sind. Alle Vergleichsoperatoren sollten const-Memberfunktionen sein.main.cpp: Lies sechs Ganzzahlen aus der Eingabe ein, die zwei Versionen darstellen (major1, minor1, patch1, major2, minor2, patch2 in separaten Zeilen). Erstelle zweiVersion-Objekte und vergleiche sie mithilfe all deiner Operatoren.Ausgabeformat:
Version 1: <v1> Version 2: <v2> v1 == v2: <true/false> v1 != v2: <true/false> v1 < v2: <true/false> v1 > v2: <true/false> v1 <= v2: <true/false> v1 >= v2: <true/false>Gib für jedes Vergleichsergebnis
trueoderfalse(kleingeschrieben) aus.
Die entscheidende Technik besteht hier darin, die vier abgeleiteten Operatoren (!=, >, <=, >=) ausschließlich mithilfe von == und < zu implementieren. Dadurch wird die Code-Duplizierung reduziert und sichergestellt, dass alle Operatoren konsistent bleiben, falls du die Vergleichslogik irgendwann änderst.
Konvertiere Eingabezeichenfolgen mithilfe von std::stoi() in Ganzzahlen. Verwende std::to_string(), um die Versionszeichenfolge zu erstellen. Vergiss die Header-Guards in deiner Headerdatei nicht.
Probier es selbst
#include <iostream>
#include <string>
#include "Version.h"
using namespace std;
int main() {
// Sechs Ganzzahlen für zwei Versionen einlesen
string line;
getline(cin, line);
int major1 = stoi(line);
getline(cin, line);
int minor1 = stoi(line);
getline(cin, line);
int patch1 = stoi(line);
getline(cin, line);
int major2 = stoi(line);
getline(cin, line);
int minor2 = stoi(line);
getline(cin, line);
int patch2 = stoi(line);
// TODO: Erstelle zwei Version-Objekte
// TODO: Gib Version 1 und Version 2 mit toString() aus
// TODO: Vergleiche mit allen sechs Operatoren und gib die Ergebnisse aus
// Verwende "true" oder "false" (Kleinbuchstaben) für jeden Vergleich
// Format: "v1 == v2: true" oder "v1 == v2: false"
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