Menu
Coddy logo textTech

Funciones miembro const

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

Has visto la palabra clave const en los métodos getter de la lección anterior. Pero ¿qué significa exactamente cuando const aparece después de la lista de parámetros de una función? Una función miembro const promete no modificar ninguna variable miembro del objeto.

class Rectangle {
    int width;
    int height;
public:
    Rectangle(int w, int h) : width(w), height(h) {}
    
    int getArea() const {      // función miembro const
        return width * height;  // Se permite leer los miembros
    }
    
    void setWidth(int w) {     // Non-const - modifica el objeto
        width = w;
    }
};

El const después de la lista de parámetros le indica al compilador: «Esta función no cambiará el estado del objeto». Si intentas modificar una variable miembro dentro de una función const, el compilador producirá un error.

Esto se vuelve esencial al trabajar con objetos const o referencias const. Un objeto const solo puede llamar a funciones miembro const:

void printArea(const Rectangle& rect) {
    std::cout << rect.getArea();    // OK - getArea() es const
    // rect.setWidth(10);           // ERROR - setWidth() no es const
}

Marcar las funciones como const cuando no modifican el objeto es una buena práctica. Documenta tu intención, permite que la función trabaje con objetos const y ayuda al compilador a detectar modificaciones accidentales. Cualquier función miembro que solo lea datos debe marcarse como const.

challenge icon

Desafío

Fácil

Construyamos un convertidor de temperatura que demuestre cuándo y por qué usar funciones miembro const. Crearás una clase en la que algunos métodos solo leen datos (y deberían ser const), mientras que otros modifican el estado del objeto.

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

  • Temperature.h: Define una clase Temperature que almacena un valor de temperatura y proporciona varias formas de leerlo y modificarlo. Tu clase debería tener:
    • Un miembro privado celsius (double) para almacenar la temperatura
    • Un constructor que acepte un valor inicial en Celsius
    • Un método getCelsius() que devuelva el valor almacenado. Debe ser const, ya que solo lee datos
    • Un método getFahrenheit() que calcule y devuelva la temperatura en Fahrenheit usando la fórmula celsius * 9.0 / 5.0 + 32.0, también const, ya que no modifica nada
    • Un método getKelvin() que devuelva la temperatura en Kelvin usando celsius + 273.15: también const
    • Un método setCelsius(double value) que actualice la temperatura almacenada. No puede ser const, ya que modifica el objeto
    • Un método adjustBy(double delta) que sume el delta a la temperatura actual, también no const
  • main.cpp: Demuestra cómo funcionan las funciones miembro const tanto con objetos normales como con objetos const. Lee un valor de temperatura inicial de la entrada y, después:
    • Crea un objeto Temperature con el valor introducido
    • Imprime "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"
    • Ajusta la temperatura en 10.0 grados
    • Imprime "After adjustment: <celsius>C"
    • Crea una función auxiliar void printReadings(const Temperature& temp) que acepte una referencia const e imprima "Reading: <celsius>C, <fahrenheit>F". Esta función solo puede llamar a métodos const sobre temp
    • Llama a printReadings() con tu objeto de temperatura
    • Establece la temperatura en 0.0 (punto de congelación)
    • Imprime "Freezing point: <celsius>C = <fahrenheit>F"

Da formato a todos los valores de temperatura con un decimal utilizando std::fixed y std::setprecision(1) de <iomanip>.

La idea clave aquí es que printReadings() recibe una referencia const, por lo que solo puede llamar a métodos marcados como const. Por eso es importante marcar correctamente tus métodos getter como const. Esto permite que funcionen en contextos en los que el objeto no se puede modificar.

Pruébalo tú mismo

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

// TODO: Implementa los métodos de la clase Temperature aquí
// Constructor
Temperature::Temperature(double initialCelsius) {
    // TODO: Inicializa celsius
}

// TODO: Implementa getCelsius() como const

// TODO: Implementa getFahrenheit() como const

// TODO: Implementa getKelvin() como const

// TODO: Implementa setCelsius(double value)

// TODO: Implementa adjustBy(double delta)


// TODO: Crea una función auxiliar printReadings que tome un const Temperature& 
// e imprime "Reading: <celsius>C, <fahrenheit>F"
// Note: ¡Esta función solo puede llamar métodos const en temp!


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

    // Establece el formato de salida
    cout << fixed << setprecision(1);

    // TODO: Crea un objeto Temperature con el valor de entrada

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

    // TODO: Ajusta la temperatura en 10.0 grados

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

    // TODO: Llama a printReadings() con tu objeto Temperature

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

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

    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