Menu
Coddy logo textTech

Funções de Membro Const

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 29 de 104.

Você viu a palavra-chave const em métodos getter na lição anterior. Mas o que exatamente significa quando const aparece após a lista de parâmetros de uma função? Uma função membro const promete não modificar nenhuma variável membro do objeto.

class Rectangle {
    int width;
    int height;
public:
    Rectangle(int w, int h) : width(w), height(h) {}
    
    int getArea() const {      // função membro const
        return width * height;  // A leitura de membros é permitida
    }
    
    void setWidth(int w) {     // Não-const - modifica o objeto
        width = w;
    }
};

O const após a lista de parâmetros diz ao compilador: "Esta função não alterará o estado do objeto." Se você tentar modificar uma variável de membro dentro de uma função const, o compilador produzirá um erro.

Isso se torna essencial ao trabalhar com objetos const ou referências const. Um objeto const só pode chamar funções membro const:

void printArea(const Rectangle& rect) {
    std::cout << rect.getArea();    // OK - getArea() é const
    // rect.setWidth(10);           // ERRO - setWidth() não é const
}

Marcar funções como const quando elas não modificam o objeto é uma boa prática. Isso documenta sua intenção, permite que a função funcione com objetos const e ajuda o compilador a detectar modificações acidentais. Qualquer função membro que apenas lê dados deve ser marcada como const.

challenge icon

Desafio

Fácil

Vamos construir um conversor de temperatura que demonstra quando e por que usar funções membros const. Você criará uma classe onde alguns métodos apenas leem dados (e devem ser const), enquanto outros modificam o estado do objeto.

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

  • Temperature.h: Defina uma classe Temperature que armazena um valor de temperatura e fornece várias maneiras de lê-lo e modificá-lo. Sua classe deve ter:
    • Um membro privado celsius (double) para armazenar a temperatura
    • Um construtor que recebe um valor inicial em Celsius
    • Um método getCelsius() que retorna o valor armazenado — este deve ser const, pois apenas lê dados
    • Um método getFahrenheit() que calcula e retorna a temperatura em Fahrenheit usando a fórmula celsius * 9.0 / 5.0 + 32.0 — também const, pois não modifica nada
    • Um método getKelvin() que retorna a temperatura em Kelvin usando celsius + 273.15 — const também
    • Um método setCelsius(double value) que atualiza a temperatura armazenada — este não pode ser const, pois modifica o objeto
    • Um método adjustBy(double delta) que adiciona o delta à temperatura atual — também não-const
  • main.cpp: Demonstre como as funções membros const funcionam com objetos regulares e const. Leia um valor de temperatura inicial da entrada e, em seguida:
    • Crie um objeto Temperature com o valor de entrada
    • Imprima "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"
    • Ajuste a temperatura em 10.0 graus
    • Imprima "After adjustment: <celsius>C"
    • Crie uma função auxiliar void printReadings(const Temperature& temp) que recebe uma referência const e imprime "Reading: <celsius>C, <fahrenheit>F" — esta função só pode chamar métodos const em temp
    • Chame printReadings() com seu objeto de temperatura
    • Defina a temperatura como 0.0 (ponto de congelamento)
    • Imprima "Freezing point: <celsius>C = <fahrenheit>F"

Formate todos os valores de temperatura com uma casa decimal usando std::fixed e std::setprecision(1) de <iomanip>.

A ideia principal aqui é que printReadings() recebe uma referência const, portanto, só pode chamar métodos marcados como const. É por isso que marcar corretamente seus métodos getter como const é importante — isso permite que eles funcionem em contextos onde o objeto não pode ser modificado.

Folha de consulta

Uma função membro const promete não modificar nenhuma variável membro do objeto. A palavra-chave const é colocada após a lista de parâmetros da função:

class Rectangle {
    int width;
    int height;
public:
    int getArea() const {      // função membro const
        return width * height;  // Ler membros é permitido
    }
    
    void setWidth(int w) {     // Não-const - modifica o objeto
        width = w;
    }
};

Funções membro const podem apenas ler variáveis membro, não modificá-las. Se você tentar modificar uma variável membro dentro de uma função const, o compilador produzirá um erro.

Um objeto const ou uma referência const só pode chamar funções membro const:

void printArea(const Rectangle& rect) {
    std::cout << rect.getArea();    // OK - getArea() é const
    // rect.setWidth(10);           // ERRO - setWidth() não é const
}

Marque funções como const quando elas não modificarem o objeto. Isso documenta sua intenção, permite que a função funcione com objetos const e ajuda o compilador a capturar modificações acidentais. Qualquer função membro que apenas lê dados deve ser marcada como const.

Experimente você mesmo

#include <iostream>
#include <iomanip>
#include "Temperature.h"
using namespace std;

// TODO: Implementar os métodos da classe Temperature aqui
// Construtor
Temperature::Temperature(double initialCelsius) {
    // TODO: Inicializar celsius
}

// TODO: Implementar getCelsius() como const

// TODO: Implementar getFahrenheit() como const

// TODO: Implementar getKelvin() como const

// TODO: Implementar setCelsius(double value)

// TODO: Implementar adjustBy(double delta)


// TODO: Criar uma função auxiliar printReadings que recebe um const Temperature& 
// e imprime "Reading: <celsius>C, <fahrenheit>F"
// Note: Esta função só pode chamar métodos const em temp!


int main() {
    double initialTemp;
    cin >> initialTemp;

    // Configurar a formatação da saída
    cout << fixed << setprecision(1);

    // TODO: Criar um objeto Temperature com o valor de entrada

    // TODO: Imprimir "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"

    // TODO: Ajustar a temperatura em 10.0 graus

    // TODO: Imprimir "After adjustment: <celsius>C"

    // TODO: Chamar printReadings() com o seu objeto de temperatura

    // TODO: Definir a temperatura para 0.0 (ponto de congelamento)

    // TODO: Imprimir "Freezing point: <celsius>C = <fahrenheit>F"

    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