Überladung der Operatoren [] und ()
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];
}
};Beachte, dass wir zwei Versionen bereitstellen: Eine gibt eine nicht-konstante Referenz zurück (und ermöglicht Änderungen), während die const-Version mit const-Objekten funktioniert. Dadurch kannst du zum Lesen und Schreiben arr[0] = 5; 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
EinfachErstelle eine ScoreTracker-Klasse, die sowohl den Subscript- als auch den Funktionsaufrufoperator kombiniert. Diese Klasse speichert die Punktzahlen der Spieler und ermöglicht den Zugriff über einen Index mit []. Gleichzeitig fungiert sie als Funktor, der auf jede übergebene Punktzahl einen Bonusmultiplikator anwendet.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
ScoreTracker.h: Definiere eineScoreTracker-Klasse, die ein Array mit den Punktzahlen der Spieler verwaltet und Boni anwenden kann. Deine Klasse sollte Folgendes enthalten:- Ein dynamisch reserviertes
int*-Array zum Speichern der Punktzahlen - Ein
size_t-Member für die Anzahl der Punktzahlen - Ein
double-Member für den Bonusmultiplikator - Einen Konstruktor, der die Größe und den Bonusmultiplikator übernimmt und alle Punktzahlen mit 0 initialisiert
- Einen Destruktor, der den dynamischen Speicher ordnungsgemäß freigibt
- Den Subscript-Operator
[](sowohl in der const- als auch in der nicht-const-Version) für den Zugriff auf Punktzahlen über einen Index - Den Funktionsaufrufoperator
(), der eineint-Punktzahl übernimmt und die mit dem Bonusmultiplikator multiplizierte Punktzahl (alsint) zurückgibt - Eine
getSize()-Methode, die die Anzahl der Punktzahlen zurückgibt
Der nicht-const Subscript-Operator gibt eine Referenz zurück, sodass du
tracker[0] = 100;schreiben kannst. Die const-Version ermöglicht den schreibgeschützten Zugriff für const-Objekte. Der Funktionsaufrufoperator sollte alsconstmarkiert werden, da er den Zustand des Objekts nicht verändert.- Ein dynamisch reserviertes
main.cpp: Lies die folgenden Eingaben ein (jeweils in einer eigenen Zeile):- Anzahl der Spieler (Größe)
- Bonusmultiplikator (als double)
- Punktzahlen für jeden Spieler (eine pro Zeile, so viele wie die Größe angibt)
- Eine Testpunktzahl, auf die der Bonus angewendet werden soll
Erstelle einen
ScoreTracker, verwende den Subscript-Operator, um die Punktzahl jedes Spielers zu speichern, und gib anschließend alle Punktzahlen aus. Verwende schließlich den Funktionsaufrufoperator, um die Punktzahl mit angewendetem Bonus zu berechnen.Ausgabeformat:
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
Beispiel: Bei 3 Spielern, einem Multiplikator von 1.5, Punktzahlen von 100, 200, 150 und einer Testpunktzahl von 80:
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120Verwende std::stoi() und std::stod() für die Konvertierung der Eingaben. Vergiss die Include-Guards in deiner Header-Datei nicht.
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 & 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