Überladen der [] und () Operatoren
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 45 von 104.
Der Indexoperator ([]) ermöglicht es Ihrer Klasse, sich wie ein Array zu verhalten, und bietet indizierten Zugriff auf Elemente. Der Funktionsaufruf-Operator (()) macht Objekte zu aufrufbaren Entitäten, bekannt als Funktoren.
Hier ist ein einfacher Array-Wrapper mit dem Subskript-Operator:
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
};Beachten Sie, dass wir zwei Versionen bereitstellen: Eine gibt eine Nicht-const-Referenz zurück (was Modifikationen ermöglicht), und die const-Version arbeitet mit const-Objekten. Dies ermöglicht es Ihnen, arr[0] = 5; zum Lesen und Schreiben zu schreiben.
Der Funktionsaufruf-Operator erzeugt Objekte, die wie Funktionen „aufgerufen“ werden können:
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // Gibt 30 zurückFunktoren sind leistungsstark, weil sie im Gegensatz zu regulären Funktionen den Zustand zwischen Aufrufen beibehalten können. Sie werden häufig mit STL-Algorithmen verwendet, wenn Sie ein anpassbares Verhalten benötigen, das sich Konfigurationswerte merkt.
Aufgabe
EinfachLassen Sie uns eine ScoreTracker-Klasse erstellen, die sowohl den Subskript- als auch den Funktionsaufruf-Operator kombiniert. Diese Klasse speichert Punktzahlen für Spieler und ermöglicht den Zugriff darauf über den Index mit [], während sie gleichzeitig als Funktor fungiert, der einen Bonus-Multiplikator auf jede übergebene Punktzahl anwendet.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
ScoreTracker.h: Definieren Sie eineScoreTracker-Klasse, die ein Array von Spieler-Punktzahlen verwaltet und Boni anwenden kann. Ihre Klasse sollte Folgendes enthalten:- Ein dynamisch zugewiesenes
int*-Array zum Speichern der Punktzahlen - Ein
size_t-Mitglied für die Anzahl der Punktzahlen - Ein
double-Mitglied für den Bonus-Multiplikator - Einen Konstruktor, der die Größe und den Bonus-Multiplikator entgegennimmt und alle Punktzahlen mit 0 initialisiert
- Einen Destruktor, der den dynamischen Speicher ordnungsgemäß bereinigt
- Den Subskript-Operator
[](sowohl in der const- als auch in der non-const-Version), um auf Punktzahlen über den Index zuzugreifen - Den Funktionsaufruf-Operator
(), der eineint-Punktzahl entgegennimmt und die mit dem Bonus-Multiplikator multiplizierte Punktzahl (alsint) zurückgibt - Eine
getSize()-Methode, welche die Anzahl der Punktzahlen zurückgibt
Der non-const Subskript-Operator gibt eine Referenz zurück, sodass Sie
tracker[0] = 100;schreiben können. Die const-Version ermöglicht den schreibgeschützten Zugriff für const-Objekte. Der Funktionsaufruf-Operator sollte alsconstmarkiert werden, da er den Zustand des Objekts nicht verändert.- Ein dynamisch zugewiesenes
main.cpp: Lesen Sie die folgenden Eingaben ein (jede in einer separaten Zeile):- Anzahl der Spieler (Größe)
- Bonus-Multiplikator (als double)
- Punktzahlen für jeden Spieler (eine pro Zeile, so viele wie die Größe)
- Eine Test-Punktzahl, auf die der Bonus angewendet werden soll
Erstellen Sie einen
ScoreTracker, verwenden Sie den Subskript-Operator, um die Punktzahl jedes Spielers zu speichern, und zeigen Sie dann alle Punktzahlen an. Verwenden Sie schließlich den Funktionsaufruf-Operator, um die Punktzahl mit angewendetem Bonus zu berechnen.Ausgabeformat:
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
Zum Beispiel bei 3 Spielern, einem Multiplikator von 1.5, Punktzahlen von 100, 200, 150 und einer Test-Punktzahl von 80:
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120Verwenden Sie std::stoi() und std::stod() für die Eingabekonvertierung. Vergessen Sie nicht die Header-Guards in Ihrer Header-Datei.
Spickzettel
Der Subskript-Operator [] ermöglicht den Zugriff auf Objekte wie bei Arrays. Der Funktionsaufruf-Operator () macht Objekte wie Funktionen aufrufbar (Funktoren).
Subskript-Operator
Stellen Sie sowohl const- als auch non-const-Versionen für den Lese-/Schreibzugriff bereit:
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
// Non-const version: allows modification
int& operator[](size_t index) {
return data[index];
}
// Const version: read-only access
const int& operator[](size_t index) const {
return data[index];
}
};Funktionsaufruf-Operator
Erzeugt Funktoren, die einen Zustand zwischen Aufrufen beibehalten können:
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // Returns 30Funktoren sind nützlich bei STL-Algorithmen, wenn anpassbares Verhalten mit gespeicherter Konfiguration erforderlich ist.
Probier es selbst
#include <iostream>
#include <string>
#include "ScoreTracker.h"
using namespace std;
// TODO: ScoreTracker-Konstruktor implementieren
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
// TODO: Member initialisieren und dynamisches Array allokieren
// Alle Spielstände auf 0 initialisieren
}
// TODO: ScoreTracker-Destruktor implementieren
ScoreTracker::~ScoreTracker() {
// TODO: Dynamischen Speicher bereinigen
}
// TODO: Nicht-konstanten Subscript-Operator implementieren
// TODO: Konstanten Subscript-Operator implementieren
// TODO: Funktionsaufruf-Operator implementieren
// TODO: getSize-Methode implementieren
size_t ScoreTracker::getSize() const {
// TODO: Die Anzahl der Spielstände zurückgeben
}
int main() {
string line;
// Anzahl der Spieler einlesen
getline(cin, line);
size_t numPlayers = stoi(line);
// Bonus-Multiplikator einlesen
getline(cin, line);
double multiplier = stod(line);
// TODO: ScoreTracker mit numPlayers und multiplier erstellen
// TODO: Spielstände für jeden Spieler einlesen und mit dem Subscript-Operator speichern
// TODO: Test-Spielstand einlesen
// TODO: Alle Spieler-Spielstände im Format "Player X: <score>" anzeigen
// TODO: Ergebnis des angewendeten Bonus im Format "Bonus applied to <test_score>: <result>" anzeigen
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