Vergleichsoperatorüberladung
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 42 von 104.
Vergleichsoperatoren wie ==, !=, <code><, , <= und >= ermöglichen es Ihnen, Objekte Ihrer benutzerdefinierten Klassen zu vergleichen. Diese Operatoren geben einen bool zurück und sollten als const gekennzeichnet werden, da sie keinen der 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 auf der Grundlage derer zu implementieren, die Sie bereits definiert haben. Sobald Sie == und <code>< haben, ergibt sich der Rest von selbst:
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 Code-Duplizierung und stellt sicher, dass sich alle Ihre Vergleichsoperatoren konsistent verhalten. Wenn Sie später ändern, wie Gleichheit oder „kleiner als“ funktioniert, bleiben die anderen Operatoren automatisch synchron.
Aufgabe
EinfachLassen Sie uns eine Version-Klasse erstellen, die Software-Versionsnummern (wie 2.1.0 oder 3.0.5) darstellt und alle sechs Vergleichsoperatoren unterstützt. Dies ist ein praktischer Anwendungsfall, bei dem der Vergleich von Versionen bestimmt, welche Software neuer ist — perfekt zum Üben des Überladens von Vergleichsoperatoren.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
Version.h: Definieren Sie eineVersion-Klasse, die drei Ganzzahlen speichert, welche die Major-, Minor- und Patch-Versionsnummern repräsentieren. Ihre Klasse sollte Folgendes unterstützen:- Einen Konstruktor, der Werte für Major, Minor und Patch entgegennimmt
- Getter für jede Komponente:
getMajor(),getMinor(),getPatch()(alle const) - Alle sechs Vergleichsoperatoren:
==,!=,<,>,<=,>= - Eine
toString()-Methode, welche die Version als String im Format"major.minor.patch"zurückgibt
Implementieren Sie
==und<direkt und definieren Sie dann die verbleibenden vier Operatoren basierend auf diesen beiden. Vergleichen Sie beim Kleiner-als-Vergleich zuerst Major, dann Minor (falls die Major-Werte gleich sind) und schließlich Patch (falls sowohl Major als auch Minor gleich sind). Alle Vergleichsoperatoren sollten const-Memberfunktionen sein.main.cpp: Lesen Sie sechs Ganzzahlen aus der Eingabe ein, die zwei Versionen repräsentieren (major1, minor1, patch1, major2, minor2, patch2 in separaten Zeilen). Erstellen Sie zweiVersion-Objekte und vergleichen Sie diese mit all Ihren 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>Geben Sie
trueoderfalse(kleingeschrieben) für jedes Vergleichsergebnis aus.
Die entscheidende Technik hierbei ist die Implementierung der vier abgeleiteten Operatoren (!=, >, <=, >=) unter ausschließlicher Verwendung von == und <. Dies reduziert Code-Duplizierung und stellt sicher, dass alle Operatoren konsistent bleiben, falls Sie jemals die Vergleichslogik ändern.
Konvertieren Sie Eingabestrings mit std::stoi() in Ganzzahlen. Verwenden Sie std::to_string() zum Erstellen des Versions-Strings. Vergessen Sie nicht die Header-Guards in Ihrer Header-Datei.
Spickzettel
Vergleichsoperatoren (==, !=, <code><, , <=, >=) ermöglichen es Ihnen, Objekte benutzerdefinierter Klassen zu vergleichen. Diese Operatoren geben einen bool zurück und sollten als const markiert werden, da sie keinen der 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;
}
};Implementieren Sie andere Vergleichsoperatoren basierend auf == und <code><, um Code-Duplizierung zu reduzieren und Konsistenz zu gewährleisten:
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);
}Probier es selbst
#include <iostream>
#include <string>
#include "Version.h"
using namespace std;
int main() {
// Lies sechs Ganzzahlen für zwei Versionen ein
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 unter Verwendung aller sechs Operatoren und gib die Ergebnisse aus
// Verwende "true" oder "false" (kleingeschrieben) 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 & 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