Menu
Coddy logo textTech

Parola chiave mutable

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 30 di 104.

Hai imparato che le funzioni membro const non possono modificare alcuna variabile membro. Ma a volte devi modificare un membro che non influisce sullo stato logico dell'oggetto, come una cache o un contatore di accessi. La parola chiave mutable costituisce un'eccezione alla restrizione const.

Un membro modificabile può essere modificato anche all'interno di una funzione membro const:

class DataFetcher {
    std::string data;
    mutable int accessCount;    // Può essere modificato nelle funzioni const
    
public:
    DataFetcher(std::string d) : data(d), accessCount(0) {}
    
    std::string getData() const {
        accessCount++;          // Consentito perché accessCount è mutable
        return data;
    }
    
    int getAccessCount() const {
        return accessCount;
    }
};

Senza mutable, incrementare accessCount all'interno della funzione const getData() causerebbe un errore del compilatore. La parola chiave mutable dice al compilatore: "Questo membro può cambiare anche quando l'oggetto è considerato const."

I casi d’uso più comuni di mutabile includono la memorizzazione nella cache dei valori calcolati, il monitoraggio delle statistiche di accesso e primitive di sincronizzazione come i mutex. In ciascun caso, la modifica non cambia ciò che l’oggetto rappresenta logicamente: un valore memorizzato nella cache è solo un’ottimizzazione e un contatore degli accessi è un metadato sull’utilizzo.

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;
    }
};

Usa mutable con parsimonia: dovrebbe essere applicato solo ai membri che non influiscono sullo stato osservabile dell'oggetto.

challenge icon

Sfida

Facile

Creiamo un visualizzatore di documenti che tenga traccia di quante volte è stato visualizzato un documento, senza compromettere la correttezza rispetto a const dei nostri metodi di sola lettura. Questo è un caso d’uso perfetto per la parola chiave mutable.

Creerai due file per organizzare il codice:

  • Document.h: definisci una classe Document che memorizza il contenuto e tiene segretamente traccia delle statistiche di visualizzazione. La classe deve includere:
    • Membri privati: title (stringa), content (stringa) e un mutable int viewCount che può essere modificato anche nei metodi const
    • Un costruttore che accetta un titolo e un contenuto e inizializza viewCount a 0
    • Un metodo const getTitle() che restituisce il titolo
    • Un metodo const getContent() che incrementa viewCount (consentito perché è mutable) e restituisce il contenuto
    • Un metodo const getViewCount() che restituisce quante volte è stato consultato il contenuto
    • Un metodo const getPreview() che restituisce i primi 20 caratteri del contenuto seguiti da "...". NON deve incrementare il conteggio delle visualizzazioni, perché si tratta solo di un’anteprima
  • main.cpp: mostra come mutable consenta di tenere traccia delle statistiche di accesso mantenendo i metodi logicamente const. Leggi da input il titolo e il contenuto di un documento (ciascuno su una riga separata), poi:
    • Crea un Document con i valori di input
    • Stampa "Title: <title>"
    • Stampa "Preview: <preview>"
    • Stampa "Views after preview: <count>"
    • Accedi al contenuto completo usando getContent() e stampa "Content: <content>"
    • Stampa "Views after first read: <count>"
    • Accedi di nuovo al contenuto e stampa "Content: <content>"
    • Stampa "Views after second read: <count>"
    • Crea una funzione di supporto void displayDocument(const Document& doc) che stampa "[Const Access] <title>: <content>". Questo dimostra che i nostri metodi const funzionano con riferimenti const
    • Chiama displayDocument() passando il tuo documento
    • Stampa "Final view count: <count>"

Il conteggio delle visualizzazioni dovrebbe essere 0 dopo l’anteprima (dato che le anteprime non contano come visualizzazioni complete), poi dovrebbe aumentare ogni volta che viene chiamato getContent(). La parola chiave mutable lo rende possibile: senza di essa, non potresti modificare viewCount all’interno di metodi const come getContent().

Se il contenuto è più corto di 20 caratteri, getPreview() dovrebbe restituire l’intero contenuto seguito da "...".

Provalo tu

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

// TODO: Implementa la funzione displayDocument
// Deve stampare: "[Const Access] <title>: <content>"
void displayDocument(const Document& doc) {
    // TODO: Implementa questa funzione
}

int main() {
    // Leggi l'input
    string title;
    string content;
    getline(cin, title);
    getline(cin, content);
    
    // TODO: Crea un Document con i valori di input
    
    // TODO: Stampa "Title: <title>"
    
    // TODO: Stampa "Preview: <preview>"
    
    // TODO: Stampa "Views after preview: <count>"
    
    // TODO: Accedi al contenuto completo e stampa "Content: <content>"
    
    // TODO: Stampa "Views after first read: <count>"
    
    // TODO: Accedi nuovamente al contenuto e stampa "Content: <content>"
    
    // TODO: Stampa "Views after second read: <count>"
    
    // TODO: Chiama displayDocument() con il tuo documento
    
    // TODO: Stampa "Final view count: <count>"
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online