Const Correctness
Parte de la sección Programación Orientada a Objetos del Journey de C de Coddy. Lección 8 de 61.
Al escribir funciones que actúan como métodos, algunas deben modificar el objeto (como player_take_damage), mientras que otras solo deben leer datos sin cambiar nada. La palabra clave const te permite aplicar esta distinción en el nivel del compilador.
Al marcar un parámetro de puntero como const, prometes que la función no modificará los datos a los que apunta. Si intentas cambiar accidentalmente un miembro, el compilador producirá un error:
typedef struct {
int x;
int y;
} Point;
// Esta función solo puede LEER el punto
void point_print(const Point *self) {
printf("(%d, %d)\n", self->x, self->y);
// self->x = 10; // ERROR: no se puede modificar a través de un puntero const
}
// Esta función puede MODIFICAR el punto
void point_move(Point *self, int dx, int dy) {
self->x += dx;
self->y += dy;
}
El parámetro const Point *self indica tanto al compilador como a otros programadores que point_print es una operación de «getter» o de solo lectura. Esto se denomina corrección de const: usar const siempre que no sea necesaria ninguna modificación.
Esta práctica detecta los errores pronto. Si escribes una función de visualización y modificas accidentalmente un campo, el compilador se detiene inmediatamente en lugar de permitir que el error se cuele en tu programa.
Desafío
FácilConstruyamos un módulo Temperature que almacene un valor de temperatura y proporcione operaciones tanto de solo lectura como de modificación. Esto te ayudará a practicar el uso de punteros const para distinguir claramente entre las funciones que solo leen datos y aquellas que los cambian.
Crearás tres archivos:
temperature.h: declara una estructuraTemperaturecon un único miembrodouble celsius. Declara también tres funciones:temp_display: recibe un punteroconsta Temperature e imprime la temperatura actual (solo lectura)temp_adjust: recibe un puntero regular a Temperature y una cantidad double; después suma la cantidad a celsius (modificación)temp_to_fahrenheit: recibe un punteroconsta Temperature y devuelve el valor convertido a Fahrenheit (solo lectura)
TEMPERATURE_H.temperature.c: implementa las tres funciones. La funcióntemp_displaydebe imprimir con el formatoCurrent: {celsius}C. La funcióntemp_to_fahrenheitdebe devolvercelsius * 9.0 / 5.0 + 32.0. Recuerda que las funciones que usan punterosconstno pueden modificar los datos de la estructura.main.c: crea un Temperature, realiza operaciones y muestra los resultados.
Recibirás dos entradas: el valor inicial en grados Celsius (como double) y la cantidad de ajuste (como double).
En tu archivo principal:
- Inicializa un
Temperaturecon el valor inicial en grados Celsius - Llama a
temp_displaypara mostrar la temperatura inicial - Llama a
temp_adjustpara modificar la temperatura según la cantidad de ajuste - Llama de nuevo a
temp_displaypara mostrar la temperatura actualizada - Imprime la conversión a Fahrenheit usando
temp_to_fahrenheit
Imprime los resultados con este formato:
Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}FUsa %.1f para todos los valores de temperatura, de modo que se muestre una cifra decimal.
Por ejemplo, con un valor inicial de 20.0 y un ajuste de 5.0, la salida sería:
Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0FPruébalo tú mismo
#include <stdio.h>
#include "temperature.h"
int main() {
double initial_celsius, adjustment;
scanf("%lf", &initial_celsius);
scanf("%lf", &adjustment);
// TODO: Crea una estructura Temperature e inicialízala con initial_celsius
// TODO: Llama a temp_display para mostrar la temperatura inicial
// TODO: Llama a temp_adjust para modificar la temperatura por la cantidad de ajuste
// TODO: Llama a temp_display de nuevo para mostrar la temperatura actualizada
// TODO: Imprime la conversión a Fahrenheit usando temp_to_fahrenheit
// Formato: "Fahrenheit: %.1fF\n"
return 0;
}
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
1Fundamentos de programación modular
Archivos de cabeceraGuardas de inclusiónArchivos fuenteFunciones estáticasRepaso: Calculadora modular4Encapsulamiento
Concepto de punteros opacosDefinición de structs opacosGetters y SettersValidación en settersResumen: Caja secreta7Punteros a funciones
Declaración de punteros a funcionesLlamada a punteros a funcionesTypedef para punteros a funcionesPasar funciones como argumentosRepaso: Dispatch de calculadora10Contenedores genéricos
Repaso de punteros voidWrapper genéricoSwap genéricoComparación genéricaRepaso: Array genérico2Objetos y métodos
Structs como objetosEl puntero 'Self'Const CorrectnessPuntero vs. ValorMétodos auxiliaresResumen: Point Manager5Proyecto: Cuenta bancaria simple
Configuración del proyectoImplementación de la cuenta3Ciclo de vida de los objetos
Patrón ConstructorPatrón DestructorInicialización en StackCopia profundaResumen: String Wrapper6Herencia mediante composición
Incrustación de StructsLa regla del primer miembroAcceso a miembros padreUpcastingResumen: Jerarquía de formas9Proyecto: Dibujador de figuras
Descripción general del proyectoImplementación del círculoImplementación del rectánguloUso polimórficoContenedor de figurasPractica por tu cuenta: Compilador de C online