Acceso a miembros padre
Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 30 de 61.
Ahora que entendemos la incrustación de estructuras y la regla del primer miembro, centrémonos en el lado práctico: cómo leer y modificar los datos del padre incrustado desde dentro de una función.
Cuando una función recibe una estructura Child (o un puntero a una), acceder a los miembros del padre requiere navegar a través de la estructura embebida. La sintaxis depende de si se está trabajando con un valor o un puntero.
typedef struct {
int id;
int score;
} Parent;
typedef struct {
Parent parent;
char grade;
} Child;Con un puntero a Child, usa el operador flecha para llegar al parent, luego el punto para acceder a sus miembros:
void update_score(Child* c, int new_score) {
c->parent.score = new_score; // Flecha y luego punto
}
void print_info(Child* c) {
printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}Con un valor (pasado por copia), usa puntos en todo momento:
void show_id(Child c) {
printf("ID: %d\n", c.parent.id); // Punto tras punto
}Este patrón de acceso encadenado — child->parent.member o child.parent.member — es cómo interactúas con los datos heredados en el modelo de composición de C. Es ligeramente más verboso que la herencia real, pero es explícito y claro sobre la relación entre los tipos.
Desafío
FácilVamos a construir un sistema de calificación de estudiantes que demuestre cómo acceder y modificar datos dentro de un struct embebido. Crearás una jerarquía donde un Student contiene un Person embebido, y luego escribirás funciones que trabajen con los datos del padre a través del hijo.
Organizarás tu código en tres archivos:
student.h: Define tu jerarquía de structs con guardas de inclusión. Crea un structPersonconname(un arreglo de caracteres de 50 caracteres) yage(un entero). Luego define un structStudentque embeba aPersoncomo su primer miembro y añada un campograde(un entero que representa su puntuación). Declara dos funciones:set_person_ageque recibe unStudent*y un nuevo valor de edad, yprint_studentque recibe unStudent*y muestra toda la información.student.c: Implementa ambas funciones. Tu funciónset_person_agedebe modificar la edad dentro del structPersonembebido; aquí es donde practicarás la sintaxis de flecha y luego punto (s->person.age). Tu funciónprint_studentdebe acceder y mostrar todos los campos tanto de la persona embebida como del propio estudiante.main.c: Crea una variableStudente inicializa todos sus campos. Luego usaset_person_agepara actualizar la edad de la persona embebida y llama aprint_studentpara mostrar el resultado.
Recibirás cuatro entradas: el name del estudiante (una cadena), su initial age (un entero), su grade (un entero) y una new age (un entero para actualizar a través de tu función).
En tu archivo principal, crea el estudiante con los valores iniciales, luego llama a set_person_age para cambiar la edad al nuevo valor y, finalmente, llama a print_student para mostrar la información actualizada.
Tu salida debería verse así:
Name: Emma
Age: 21
Grade: 85Donde Emma es el nombre, 21 es la edad actualizada (no la edad inicial) y 85 es la calificación. El aprendizaje clave aquí es navegar a través del struct embebido tanto para leer como para escribir los miembros del padre.
Hoja de referencia
Para acceder a los miembros de una estructura padre incrustada desde una función, utilice la sintaxis de acceso encadenado que depende de si está trabajando con un puntero o con un valor.
Con un puntero a la estructura hija, utilice el operador de flecha para llegar al padre incrustado y, a continuación, la notación de punto para acceder a sus miembros:
void update_score(Child* c, int new_score) {
c->parent.score = new_score; // Flecha y luego punto
}
void print_info(Child* c) {
printf("ID: %d, Score: %d\n", c->parent.id, c->parent.score);
}Con un valor (pasado por copia), utilice la notación de punto en todo momento:
void show_id(Child c) {
printf("ID: %d\n", c.parent.id); // Punto y luego punto
}Este patrón — child->parent.member o child.parent.member — proporciona acceso explícito a los datos heredados en el modelo de composición de C.
Pruébalo tú mismo
#include <stdio.h>
#include <string.h>
#include "student.h"
int main() {
char name[50];
int initial_age, grade, new_age;
// Leer entradas
fgets(name, 50, stdin);
name[strcspn(name, "\n")] = '\0'; // Eliminar el salto de línea
scanf("%d", &initial_age);
scanf("%d", &grade);
scanf("%d", &new_age);
// TODO: Crear una variable Student
// TODO: Inicializar todos los campos del estudiante
// - Copiar name al nombre de la persona embebida usando strcpy
// - Establecer la edad de la persona embebida a initial_age
// - Establecer el grado (grade) del estudiante
// TODO: Llamar a set_person_age para actualizar la edad a new_age
// TODO: Llamar a print_student para mostrar el resultado
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