Menu
Coddy logo textTech

Ü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ück

Funktoren 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.

challenge icon

Aufgabe

Einfach

Lassen 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 eine ScoreTracker-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 eine int-Punktzahl entgegennimmt und die mit dem Bonus-Multiplikator multiplizierte Punktzahl (als int) 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 als const markiert werden, da er den Zustand des Objekts nicht verändert.

  • main.cpp: Lesen Sie die folgenden Eingaben ein (jede in einer separaten Zeile):
    1. Anzahl der Spieler (Größe)
    2. Bonus-Multiplikator (als double)
    3. Punktzahlen für jeden Spieler (eine pro Zeile, so viele wie die Größe)
    4. 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: 120

Verwenden 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 30

Funktoren 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;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung