Menu
Coddy logo textTech

Upcasting

Parte de la sección Programación Orientada a Objetos del Journey de C de Coddy. Lección 31 de 61.

La conversión ascendente es el acto de tratar un tipo específico (derivado) como su tipo más general (base). En el modelo de composición de C, esto significa pasar un puntero a una estructura que incorpora un tipo base a una función que espera el tipo base.

Considera una estructura base Vehicle y un Car que la contiene:

typedef struct {
    int speed;
} Vehicle;

typedef struct {
    Vehicle vehicle;  // Base como primer miembro
    int doors;
} Car;

Ahora imagina una función genérica que funciona con cualquier vehículo:

void accelerate(Vehicle* v, int amount) {
    v->speed += amount;
}

Gracias a la regla del primer miembro, podemos pasar un Car* a esta función convirtiéndolo a Vehicle*:

Car my_car = {{0}, 4};  // speed=0, doors=4
accelerate((Vehicle*)&my_car, 50);
printf("Speed: %d\n", my_car.vehicle.speed);  // Salida: 50

Esto es un upcasting: estamos subiendo desde un tipo específico a uno general. La función accelerate no sabe que está trabajando con un Car; solo ve un Vehicle. Esto te permite escribir código reutilizable que opera sobre el tipo base y acepta cualquier tipo derivado que lo incorpore.

challenge icon

Desafío

Fácil

Construyamos un sistema de transporte sencillo que demuestre el upcasting en acción. Crearás un tipo base Vehicle y un tipo más específico Motorcycle, después mostrarás cómo una función genérica puede trabajar con ambos mediante la conversión de punteros.

El poder del upcasting es que puedes escribir funciones para el tipo base, y funcionarán sin problemas con cualquier tipo derivado que lo incluya. Tu Motorcycle "is a" vehículo, así que cualquier función que espere un Vehicle* debería poder procesarlo.

Organizarás tu código en tres archivos:

  • vehicle.h: Define tu jerarquía de structs con include guards. Create un struct Vehicle con dos fields: speed (un entero para la velocidad current) y max_speed (un entero para la velocidad máxima del vehículo). Después define un struct Motorcycle que incluye Vehicle como su primer member y añade un campo has_sidecar (un entero, donde 1 significa sí y 0 significa no). Declara dos funciones: boost, que recibe un Vehicle* y una cantidad para Increase la velocidad, y print_motorcycle, que recibe un Motorcycle*.
  • vehicle.c: Implement ambas funciones. Tu función boost debe Increase la velocidad del vehículo en la cantidad given, pero limitarla a max_speed; si la nueva velocidad fuera a exceed el máximo, establécela en max_speed en su lugar. Tu función print_motorcycle debe mostrar all la información de la Motorcycle, incluida su información del vehículo incluido.
  • main.c: Crea una Motorcycle e initialize todos its campos. Después demuestra el upcasting llamando a la función boost: convierte tu Motorcycle* en un Vehicle* para pasarlo a esta función genérica. Después del aumento, imprime la información de la Motorcycle para ver el resultado.

Recibirás cuatro entradas: la initial speed de la Motorcycle, su max speed, si has a sidecar (1 o 0), y la boost amount.

Tu salida debería verse así:

Speed: 75
Max Speed: 120
Sidecar: Yes

Donde 75 es la velocidad después del aumento (initial 50 + boost 25), 120 es la velocidad máxima, y Yes o No indica si la Motorcycle tiene un sidecar. Si el aumento hiciera que la velocidad superara max_speed, la velocidad debería limitarse a max_speed.

El aprendizaje clave aquí es que boost no sabe nada sobre Motorcycle. Solo trabaja con Vehicle. Sin embargo, mediante el upcasting, tu Motorcycle puede usar esta función genérica para modificar sus datos del vehículo incluido.

Pruébalo tú mismo

#include <stdio.h>
#include "vehicle.h"

int main() {
    int initial_speed, max_speed, has_sidecar, boost_amount;
    
    // Leer entradas
    scanf("%d", &initial_speed);
    scanf("%d", &max_speed);
    scanf("%d", &has_sidecar);
    scanf("%d", &boost_amount);
    
    // TODO: Crea una Motorcycle e inicializa todos sus campos
    // Recuerda: Motorcycle embebe Vehicle como su primer miembro
    
    // TODO: Demuestra el upcasting llamando a boost
    // Convierte tu Motorcycle* a Vehicle* para pasarlo a la función boost
    
    // TODO: Imprime la información de la motorcycle
    
    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