Menu
Coddy logo textTech

Palabra clave mutable

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 30 de 104.

Has aprendido que las funciones miembro const no pueden modificar ninguna variable miembro. Pero a veces necesitas cambiar un miembro que no afecta al estado lógico del objeto, como una caché o un contador de accesos. La palabra clave mutable proporciona una excepción a la restricción de const.

Un miembro mutable se puede modificar incluso dentro de una función miembro const:

class DataFetcher {
    std::string data;
    mutable int accessCount;    // Puede ser modificado en funciones const
    
public:
    DataFetcher(std::string d) : data(d), accessCount(0) {}
    
    std::string getData() const {
        accessCount++;          // Permitido porque accessCount es mutable
        return data;
    }
    
    int getAccessCount() const {
        return accessCount;
    }
};

Sin mutable, incrementar accessCount dentro de la función const getData() provocaría un error del compilador. La palabra clave mutable le indica al compilador: «Este miembro puede cambiar incluso cuando el objeto se considera const».

Los casos de uso comunes de mutable incluyen el almacenamiento en caché de valores calculados, el seguimiento de las estadísticas de access y las primitivas de sincronización, como los mutexes. En cada caso, la modificación no cambia lo que el objeto representa lógicamente: un valor almacenado en caché es simplemente una optimización, y un contador de access es metadatos sobre el uso.

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 moderación: solo debe aplicarse a miembros que no afecten al estado observable del objeto.

challenge icon

Desafío

Fácil

Construyamos un visor de documentos que registre cuántas veces se ha visto un documento, sin romper la const-corrección de nuestros métodos de solo lectura. Este es un caso de uso perfecto para la palabra clave mutable.

Crearás dos archivos para organizar tu código:

  • Document.h: Define una clase Document que almacene el contenido y registre secretamente las estadísticas de visualización. Tu clase necesita:
    • Miembros privados: title (cadena), content (cadena) y un mutable int viewCount que pueda modificarse incluso en métodos const
    • Un constructor que reciba un título y un contenido, inicializando viewCount a 0
    • Un método const getTitle() que devuelva el título
    • Un método const getContent() que incremente viewCount (está permitido porque es mutable) y devuelva el contenido
    • Un método const getViewCount() que devuelva cuántas veces se ha accedido al contenido
    • Un método const getPreview() que devuelva los primeros 20 caracteres del contenido seguidos de "...". Esto NO debe incrementar el recuento de visualizaciones, ya que solo es una vista previa
  • main.cpp: Demuestra cómo mutable permite registrar las estadísticas de acceso manteniendo los métodos lógicamente const. Lee el título y el contenido de un documento desde la entrada (cada uno en una línea separada) y después:
    • Crea un Document con los valores de entrada
    • Imprime "Title: <title>"
    • Imprime "Preview: <preview>"
    • Imprime "Views after preview: <count>"
    • Accede al contenido completo usando getContent() e imprime "Content: <content>"
    • Imprime "Views after first read: <count>"
    • Accede de nuevo al contenido e imprime "Content: <content>"
    • Imprime "Views after second read: <count>"
    • Crea una función auxiliar void displayDocument(const Document& doc) que imprima "[Const Access] <title>: <content>". Esto demuestra que nuestros métodos const funcionan con referencias const
    • Llama a displayDocument() con tu documento
    • Imprime "Final view count: <count>"

El recuento de visualizaciones debe ser 0 después de la vista previa (ya que las vistas previas no cuentan como visualizaciones completas), y después incrementarse cada vez que se llame a getContent(). La palabra clave mutable hace esto posible; sin ella, no podrías modificar viewCount dentro de métodos const como getContent().

Si el contenido tiene menos de 20 caracteres, getPreview() debe devolver todo el contenido seguido de "...".

Pruébalo tú mismo

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

// TODO: Implementa la función displayDocument
// Debería imprimir: "[Const Access] <title>: <content>"
void displayDocument(const Document& doc) {
    // TODO: Implementa esta función
}

int main() {
    // Leer la entrada
    string title;
    string content;
    getline(cin, title);
    getline(cin, content);
    
    // TODO: Crea un Document con los valores de entrada
    
    // TODO: Imprime "Title: <title>"
    
    // TODO: Imprime "Preview: <preview>"
    
    // TODO: Print "Views after preview: <count>"
    
    // TODO: Accede al contenido completo e imprime "Content: <content>"
    
    // TODO: Print "Views after first read: <count>"
    
    // TODO: Accede al contenido de nuevo e imprime "Content: <content>"
    
    // TODO: Print "Views after second read: <count>"
    
    // TODO: Llama a displayDocument() con tu documento
    
    // TODO: Print "Final view count: <count>"
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online