Structs como objetos
Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 6 de 61.
En los lenguajes orientados a objetos, un objeto es una entidad que agrupa datos (estado) con funciones que operan sobre esos datos (métodos). C no tiene objetos integrados, pero podemos lograr el mismo concepto utilizando structs y funciones.
Piense en un struct como la parte de "datos" de un objeto. Mantiene el estado: los valores que definen lo que el objeto es actualmente:
typedef struct {
int value;
} Counter;
Esta struct Counter representa una entidad con una única pieza de estado: su valor actual. Para darle comportamiento, escribimos funciones que aceptan la struct como parámetro:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
Estas funciones actúan como métodos: operan específicamente sobre los datos de Counter. Al pasar la estructura a las funciones, estamos simulando lo que otros lenguajes hacen automáticamente cuando llamas a counter.increment().
int main() {
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // Imprime: 1
return 0;
}
La convención de nomenclatura typename_action (como counter_increment) ayuda a organizar tu código y deja claro a qué struct pertenece una función. Este patrón es la base de la programación orientada a objetos en C.
Desafío
FácilVamos a construir un módulo Counter simple que trata a una estructura como un objeto con comportamiento. Organizarás tu código en tres archivos para practicar el patrón de agrupar datos con funciones que operan sobre ellos.
Crearás tres archivos:
counter.h: Tu archivo de cabecera que declara la estructuraCountercon un único miembroint value. También declara dos funciones que actúan como "métodos" para el contador:counter_increment(toma un puntero a Counter e incrementa su valor en 1) ycounter_get(toma un puntero a Counter y devuelve su valor actual). Usa guardas de inclusión con el símboloCOUNTER_H.counter.c: Tu archivo de origen que implementa ambas funciones. Recuerda incluir tu archivo de cabecera.main.c: Tu archivo principal que crea un Counter, realiza operaciones sobre él y muestra los resultados.
Recibirás dos entradas enteras: el valor inicial para tu contador y el número de veces que se debe incrementar.
En tu archivo principal, inicializa un Counter con el valor inicial, luego llama a counter_increment el número especificado de veces. Finalmente, usa counter_get para recuperar e imprimir el valor final.
Imprime el resultado en este formato:
Final value: {result}Por ejemplo, con un valor inicial de 5 y 3 incrementos, la salida sería:
Final value: 8Hoja de referencia
En C, podemos simular la programación orientada a objetos combinando structs (datos) con funciones (comportamiento) que operan sobre esos structs.
Define un struct para mantener el estado:
typedef struct {
int value;
} Counter;
Crea funciones que actúen como "métodos" aceptando el struct como parámetro:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
Usa el struct y las funciones juntos:
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // Prints: 1
La convención de nomenclatura typename_action (por ejemplo, counter_increment) ayuda a organizar el código y aclara sobre qué struct opera una función.
Pruébalo tú mismo
#include <stdio.h>
#include "counter.h"
int main() {
// Leer entrada
int starting_value;
int num_increments;
scanf("%d", &starting_value);
scanf("%d", &num_increments);
// TODO: Crear un Counter e inicializarlo con starting_value
// TODO: Llamar a counter_increment el número de veces especificado
// TODO: Usar counter_get para recuperar el valor final e imprimirlo
// Formato de impresión: "Final value: {result}"
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