Menu
Coddy logo textTech

Funções 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 nos métodos getter da 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) {     // Non-const - modifica o objeto
        width = w;
    }
};

O const após a lista de parâmetros informa ao compilador: "Esta função não alterará o estado do objeto." Se você tentar modificar uma variável-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);           // ERROR - 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 trabalhe com objetos const e ajuda o compilador a detectar modificações acidentais. Qualquer função-membro que apenas leia dados deve ser marcada como const.

challenge icon

Desafio

Fácil

Vamos criar um conversor de temperatura que demonstra quando e por que usar funções membro const. Você criará uma classe na qual 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 oferece 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. Ele 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: também const
    • Um método setCelsius(double value) que atualiza a temperatura armazenada. Ele 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 membro const funcionam com objetos comuns e const. Leia um valor inicial de temperatura 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". Essa 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 principal ideia 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 nos quais o objeto não pode ser modificado.

Experimente você mesmo

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

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

// TODO: Implemente getCelsius() como const

// TODO: Implemente getFahrenheit() como const

// TODO: Implemente getKelvin() como const

// TODO: Implemente setCelsius(double value)

// TODO: Implemente adjustBy(double delta)


// TODO: Crie 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;

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

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

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

    // TODO: Ajuste a temperatura em 10.0 graus

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

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

    // TODO: Set the temperature to 0.0 (freezing point)

    // TODO: Print "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

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