Menu
Coddy logo textTech

Mutable-Schlüsselwort

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 30 von 104.

Du hast gelernt, dass const-Memberfunktionen keine Membervariablen ändern können. Aber manchmal musst du ein Member ändern, das den logischen Zustand des Objekts nicht beeinflusst – etwa einen Cache oder einen Zugriffszähler. Das Schlüsselwort mutable bietet eine Ausnahme von der const-Beschränkung.

Ein veränderbares Mitglied kann sogar innerhalb einer const-Memberfunktion geändert werden:

class DataFetcher {
    std::string data;
    mutable int accessCount;    // Kann in const-Funktionen geändert werden
    
public:
    DataFetcher(std::string d) : data(d), accessCount(0) {}
    
    std::string getData() const {
        accessCount++;          // Erlaubt, weil accessCount mutable ist
        return data;
    }
    
    int getAccessCount() const {
        return accessCount;
    }
};

Ohne mutable würde das Erhöhen von accessCount innerhalb der const-Funktion getData() einen Compilerfehler verursachen. Das Schlüsselwort mutable teilt dem Compiler mit: „Dieses Member darf geändert werden, selbst wenn das Objekt als const betrachtet wird.“

Häufige Anwendungsfälle für veränderliche Werte sind das Zwischenspeichern berechneter Werte, das Verfolgen von Zugriffstatistiken und Synchronisierungsprimitive wie Mutexes. In jedem Fall ändert die Modifikation nicht, was das Objekt logisch darstellt – ein zwischengespeicherter Wert ist lediglich eine Optimierung, und ein Zugriffszähler sind Metadaten über die Nutzung.

class Circle {
    double radius;
    mutable double cachedArea;
    mutable bool areaCached;
    
public:
    double getArea() const {
        if (!areaCached) {
            cachedArea = 3.14159 * radius * radius;
            areaCached = true;
        }
        return cachedArea;
    }
};

Verwende mutable sparsam – es sollte nur auf Member angewendet werden, die den beobachtbaren Zustand des Objekts nicht beeinflussen.

challenge icon

Aufgabe

Einfach

Lass uns einen Dokumentbetrachter erstellen, der verfolgt, wie oft ein Dokument angesehen wurde, ohne die Const-Korrektheit unserer schreibgeschützten Methoden zu beeinträchtigen. Dies ist ein perfekter Anwendungsfall für das Schlüsselwort mutable.

Du wirst zwei Dateien erstellen, um deinen Code zu organisieren:

  • Document.h: Definiere eine Document-Klasse, die den Inhalt speichert und heimlich die Ansichtsstatistiken verfolgt. Deine Klasse benötigt:
    • Private Member: title (String), content (String) und ein mutable int viewCount, das auch in Const-Methoden geändert werden kann
    • Einen Konstruktor, der einen Titel und einen Inhalt entgegennimmt und viewCount auf 0 initialisiert
    • Eine Const-Methode getTitle(), die den Titel zurückgibt
    • Eine Const-Methode getContent(), die viewCount erhöht (weil es mutable ist) und den Inhalt zurückgibt
    • Eine Const-Methode getViewCount(), die zurückgibt, wie oft auf den Inhalt zugegriffen wurde
    • Eine Const-Methode getPreview(), die die ersten 20 Zeichen des Inhalts gefolgt von "..." zurückgibt. Diese Methode darf die Anzahl der Ansichten NICHT erhöhen, da es sich nur um eine Vorschau handelt
  • main.cpp: Zeige, wie mutable das Verfolgen von Zugriffsstatistiken ermöglicht, während die Methoden logisch const bleiben. Lies einen Dokumenttitel und einen Inhalt aus der Eingabe ein (jeweils in einer separaten Zeile), und dann:
    • Erstelle ein Document mit den Eingabewerten
    • Gib "Title: <title>" aus
    • Gib "Preview: <preview>" aus
    • Gib "Views after preview: <count>" aus
    • Greife mit getContent() auf den vollständigen Inhalt zu und gib "Content: <content>" aus
    • Gib "Views after first read: <count>" aus
    • Greife erneut auf den Inhalt zu und gib "Content: <content>" aus
    • Gib "Views after second read: <count>" aus
    • Erstelle eine Hilfsfunktion void displayDocument(const Document& doc), die "[Const Access] <title>: <content>" ausgibt. Dies beweist, dass unsere Const-Methoden mit Const-Referenzen funktionieren
    • Rufe displayDocument() mit deinem Dokument auf
    • Gib "Final view count: <count>" aus

Die Anzahl der Ansichten sollte nach der Vorschau 0 betragen (da Vorschauen nicht als vollständige Ansichten zählen) und sich dann jedes Mal erhöhen, wenn getContent() aufgerufen wird. Das Schlüsselwort mutable macht dies möglich; ohne es könntest du viewCount nicht innerhalb von Const-Methoden wie getContent() ändern.

Wenn der Inhalt kürzer als 20 Zeichen ist, sollte getPreview() den gesamten Inhalt gefolgt von "..." zurückgeben.

Probier es selbst

#include <iostream>
#include <string>
#include "Document.h"
using namespace std;

// TODO: Implementiere die displayDocument-Funktion
// Sie sollte ausgeben: "[Const Access] <title>: <content>"
void displayDocument(const Document& doc) {
    // TODO: Implementiere diese Funktion
}

int main() {
    // Eingabe lesen
    string title;
    string content;
    getline(cin, title);
    getline(cin, content);
    
    // TODO: Erstelle ein Document mit den Eingabewerten
    
    // TODO: Gib "Title: <title>" aus
    
    // TODO: Gib "Preview: <preview>" aus
    
    // TODO: Print "Views after preview: <count>"
    
    // TODO: Greife auf den vollständigen Inhalt zu und gib "Content: <content>" aus
    
    // TODO: Print "Views after first read: <count>"
    
    // TODO: Greife erneut auf den Inhalt zu und gib "Content: <content>" aus
    
    // TODO: Print "Views after second read: <count>"
    
    // TODO: Rufe displayDocument() mit deinem Document auf
    
    // TODO: Print "Final view count: <count>"
    
    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

Übe selbstständig: Online-C++-Compiler