Menu
Coddy logo textTech

Upcasting

Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 31 de 61.

Upcasting é o ato de tratar um tipo específico (derivado) como seu tipo mais geral (base). No modelo de composição de C, isso significa passar um ponteiro para uma estrutura que incorpora um tipo base a uma função que espera o tipo base.

Considere uma estrutura base Vehicle e um Car que a contém:

typedef struct {
    int speed;
} Vehicle;

typedef struct {
    Vehicle vehicle;  // Base como primeiro membro
    int doors;
} Car;

Agora imagine uma função genérica que funciona com qualquer veículo:

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

Graças à regra do primeiro membro, podemos passar um Car* para esta função convertendo-o para Vehicle*:

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

Isso é upcasting: estamos subindo de um tipo específico para um tipo geral. A função accelerate não sabe que está trabalhando com um Car; ela apenas vê um Vehicle. Isso permite escrever código reutilizável que opera no tipo base, aceitando qualquer tipo derivado que o incorpore.

challenge icon

Desafio

Fácil

Vamos construir um sistema de transporte simples que demonstra o upcasting em ação. Você criará um tipo base Vehicle e um tipo mais específico Motorcycle; em seguida, mostrará como uma função genérica pode trabalhar com ambos por meio de conversão de ponteiros.

O poder do upcasting é que você pode escrever funções para o tipo base, e elas funcionarão perfeitamente com qualquer tipo derivado que o incorpore. Sua motocicleta “é um” veículo, portanto qualquer função que espere um Vehicle* deve ser capaz de processá-la.

Você organizará seu código em três arquivos:

  • vehicle.h: Defina sua hierarquia de structs com proteções contra inclusão múltipla. Crie uma struct Vehicle com dois campos: speed (um inteiro para a velocidade atual) e max_speed (um inteiro para a velocidade máxima do veículo). Em seguida, defina uma struct Motorcycle que incorpore Vehicle como seu primeiro membro e adicione um campo has_sidecar (um inteiro, em que 1 significa sim e 0 significa não). Declare duas funções: boost, que recebe um Vehicle* e uma quantidade para aumentar a velocidade, e print_motorcycle, que recebe um Motorcycle*.
  • vehicle.c: Implemente ambas as funções. Sua função boost deve aumentar a velocidade do veículo pela quantidade fornecida, mas limitá-la a max_speed; se a nova velocidade exceder o máximo, defina-a como max_speed em vez disso. Sua função print_motorcycle deve exibir todas as informações da motocicleta, incluindo os dados do veículo incorporado.
  • main.c: Crie uma Motorcycle e inicialize todos os seus campos. Em seguida, demonstre o upcasting chamando a função boost: converta seu Motorcycle* para um Vehicle* para passá-lo a essa função genérica. Depois do aumento, imprima as informações da motocicleta para ver o resultado.

Você receberá quatro entradas: a velocidade inicial da motocicleta, sua velocidade máxima, se ela tem um sidecar (1 ou 0) e a quantidade do aumento.

Sua saída deve ser semelhante a esta:

Speed: 75
Max Speed: 120
Sidecar: Yes

Onde 75 é a velocidade após o aumento (inicial 50 + aumento 25), 120 é a velocidade máxima, e Yes ou No indica se a motocicleta tem um sidecar. Se o aumento fizer a velocidade ultrapassar max_speed, ela deverá ser limitada a max_speed.

O principal aprendizado aqui é que boost não sabe nada sobre motocicletas. Ela funciona apenas com Vehicle. No entanto, por meio do upcasting, sua motocicleta pode usar essa função genérica para modificar os dados do veículo incorporado.

Experimente você mesmo

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

int main() {
    int initial_speed, max_speed, has_sidecar, boost_amount;
    
    // Ler entradas
    scanf("%d", &initial_speed);
    scanf("%d", &max_speed);
    scanf("%d", &has_sidecar);
    scanf("%d", &boost_amount);
    
    // TODO: Crie uma Motorcycle e inicialize todos os seus campos
    // Lembre-se: Motorcycle embute Vehicle como seu primeiro membro
    
    // TODO: Demonstre upcasting chamando boost
    // Faça o cast do seu Motorcycle* para Vehicle* para passá-lo à função boost
    
    // TODO: Imprima as informações da motorcycle
    
    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