Menu
Coddy logo textTech

Palavra-chave Mutable

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 30 de 104.

Você aprendeu que funções membro const não podem modificar nenhuma variável membro. Mas às vezes você precisa alterar um membro que não afeta o estado lógico do objeto — como um cache ou um contador de acessos. A palavra-chave mutable fornece uma exceção à restrição de const.

Um membro mutável pode ser modificado mesmo dentro de uma função membro const:

class DataFetcher {
    std::string data;
    mutable int accessCount;    // Pode ser modificado em funções const
    
public:
    DataFetcher(std::string d) : data(d), accessCount(0) {}
    
    std::string getData() const {
        accessCount++;          // Permitido porque accessCount é mutable
        return data;
    }
    
    int getAccessCount() const {
        return accessCount;
    }
};

Sem mutable, incrementar accessCount dentro da função const getData() causaria um erro de compilação. A palavra-chave mutable diz ao compilador: "Este membro pode ser alterado mesmo quando o objeto é considerado const."

Casos de uso comuns para mutable incluem armazenar em cache valores calculados, acompanhar estatísticas de acesso e primitivas de sincronização, como mutexes. Em cada caso, a modificação não altera o que o objeto representa logicamente — um valor armazenado em cache é apenas uma otimização, e um contador de acesso é metadado sobre o 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;
    }
};

Use mutable com moderação — ele deve ser aplicado apenas a membros que não afetam o estado observável do objeto.

challenge icon

Desafio

Fácil

Vamos criar um visualizador de documentos que rastreia quantas vezes um documento foi visualizado, sem quebrar a correção de constância dos nossos métodos somente para leitura. Este é um caso de uso perfeito para a palavra-chave mutable.

Você criará dois arquivos para organizar seu código:

  • Document.h: Defina uma classe Document que armazena o conteúdo e rastreia discretamente as estatísticas de visualização. Sua classe precisa de:
    • Membros privados: title (string), content (string) e um mutable int viewCount que pode ser modificado até mesmo em métodos const
    • Um construtor que recebe um título e um conteúdo, inicializando viewCount com 0
    • Um método const getTitle() que retorna o título
    • Um método const getContent() que incrementa viewCount (permitido porque ele é mutable) e retorna o conteúdo
    • Um método const getViewCount() que retorna quantas vezes o conteúdo foi acessado
    • Um método const getPreview() que retorna os 20 primeiros caracteres do conteúdo seguidos por "...". Isso NÃO deve incrementar a contagem de visualizações, pois é apenas uma prévia
  • main.cpp: Demonstre como mutable permite rastrear estatísticas de acesso mantendo os métodos logicamente const. Leia um título e um conteúdo de documento da entrada (cada um em uma linha separada) e, em seguida:
    • Crie um Document com os valores de entrada
    • Imprima "Title: <title>"
    • Imprima "Preview: <preview>"
    • Imprima "Views after preview: <count>"
    • Acesse o conteúdo completo usando getContent() e imprima "Content: <content>"
    • Imprima "Views after first read: <count>"
    • Acesse o conteúdo novamente e imprima "Content: <content>"
    • Imprima "Views after second read: <count>"
    • Crie uma função auxiliar void displayDocument(const Document& doc) que imprime "[Const Access] <title>: <content>". Isso comprova que nossos métodos const funcionam com referências const
    • Chame displayDocument() com seu documento
    • Imprima "Final view count: <count>"

A contagem de visualizações deve ser 0 após a prévia (já que as prévias não contam como visualizações completas) e, em seguida, ser incrementada cada vez que getContent() for chamado. A palavra-chave mutable torna isso possível; sem ela, você não poderia modificar viewCount dentro de métodos const como getContent().

Se o conteúdo tiver menos de 20 caracteres, getPreview() deverá retornar todo o conteúdo seguido por "...".

Experimente você mesmo

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

// TODO: Implemente a função displayDocument
// Deve imprimir: "[Const Access] <title>: <content>"
void displayDocument(const Document& doc) {
    // TODO: Implemente esta função
}

int main() {
    // Ler entrada
    string title;
    string content;
    getline(cin, title);
    getline(cin, content);
    
    // TODO: Crie um Document com os valores de entrada
    
    // TODO: Imprima "Title: <title>"
    
    // TODO: Imprima "Preview: <preview>"
    
    // TODO: Print "Views after preview: <count>"
    
    // TODO: Acesse o conteúdo completo e imprima "Content: <content>"
    
    // TODO: Print "Views after first read: <count>"
    
    // TODO: Acesse o conteúdo novamente e imprima "Content: <content>"
    
    // TODO: Print "Views after second read: <count>"
    
    // TODO: Chame displayDocument() com o seu documento
    
    // TODO: Print "Final view count: <count>"
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C++ online