Incrustación de Structs
Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 28 de 61.
En lenguajes orientados a objetos como C++ o Java, la herencia permite que una clase adquiera propiedades de una clase padre. C no tiene herencia incorporada, pero podemos simularla usando una técnica llamada composición: colocar un struct dentro de otro.
La idea es sencilla: si un Child necesita todas las propiedades de un Parent, incrustamos la struct Parent como un miembro de Child.
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // Estructura embebida
int grade;
} Child;Aquí, Child contiene todo lo que Parent tiene, además de su propio campo grade. Esto es composición: el hijo "tiene un" padre en lugar de "es un" padre, pero el efecto es similar a la herencia.
Para acceder a los miembros del padre a través de una instancia hija, se utiliza el operador de punto dos veces:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;Este patrón constituye la base para construir jerarquías de tipos en C. Al incrustar una struct base como el primer miembro, desbloqueamos técnicas potentes que exploraremos en las próximas lecciones.
Desafío
FácilVamos a construir un sistema simple de gestión de empleados que demuestre la incrustación de estructuras (struct embedding), la base de la herencia en C.
Crearás una jerarquía donde un Employee contiene un Person. Esto refleja cómo funciona la herencia: un empleado "es una" persona con información adicional relacionada con el trabajo. Al incrustar la estructura Person dentro de Employee, obtienes todas las propiedades de la persona más los campos específicos del empleado.
Organizarás tu código en tres archivos:
types.h: Define ambas estructuras aquí con guardas de inclusión. Primero, crea una estructuraPersoncon dos campos:name(un arreglo de caracteres de 50 caracteres) yage(un entero). Luego, define una estructuraEmployeeque incrustePersoncomo su primer miembro y añada un campoemployee_id(un entero).types.c: Implementa una función llamadaprint_employeeque reciba un puntero a unEmployeee imprima su información. Accede a los datos de la persona incrustada utilizando la sintaxis encadenada de punto/flecha que has aprendido.main.c: Crea una variable de tipoEmployee, completa todos sus campos (incluyendo el nombre y la edad de la persona incrustada) y utiliza tu función de impresión para mostrar la información.
Recibirás tres entradas: el name del empleado (una cadena), su age (un entero) y su employee ID (un entero).
Tu función print_employee debe mostrar la información del empleado en este formato:
Employee: Alice
Age: 28
ID: 1001Donde Alice es el nombre, 28 es la edad y 1001 es el ID del empleado de tus entradas.
Recuerda acceder a los miembros de la estructura incrustada a través del miembro padre; por ejemplo, para llegar al nombre, navegarás primero a través del miembro person.
Hoja de referencia
C no tiene herencia incorporada, pero puedes simularla usando composición — incrustando una estructura dentro de otra.
Para crear una relación padre-hijo, incrusta la estructura padre como un miembro de la estructura hijo:
typedef struct {
int id;
char name[50];
} Parent;
typedef struct {
Parent parent; // Embedded struct
int grade;
} Child;La estructura hijo contiene todas las propiedades del padre, además de sus propios campos adicionales. Esto representa una relación de tipo "tiene un" (has a).
Para acceder a los miembros de la estructura incrustada, utiliza el operador de punto dos veces:
Child c;
c.parent.id = 101;
c.parent.name[0] = 'A';
c.grade = 5;Cuando trabajes con punteros, utiliza el operador de flecha para acceder a los miembros de la estructura incrustada:
Child *ptr = &c;
ptr->parent.id = 101;
ptr->grade = 5;Incrustar la estructura base como el primer miembro es un patrón común que permite técnicas avanzadas para construir jerarquías de tipos en C.
Pruébalo tú mismo
#include <stdio.h>
#include <string.h>
#include "types.h"
int main() {
// Leer entrada
char name[50];
int age;
int employee_id;
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // Eliminar el salto de línea
scanf("%d", &age);
scanf("%d", &employee_id);
// TODO: Crear una variable Employee
// TODO: Rellenar el nombre y la edad de la person incrustada
// Hint: Usa strcpy para el nombre, accede con employee.person.name
// TODO: Establecer el employee_id
// TODO: Llamar a print_employee con un puntero a tu employee
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
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írculo