-
Notifications
You must be signed in to change notification settings - Fork 0
Ejemplo POO 3
Siguiendo el ejemplo anterior (ejemplo POO 2) para la definición de clases y ejecución de objetos en C, si se sabe que los objetos consumen mucha memoria es recomendable que utilicen memoria del heap, de esta forma se reduce el riesgo de saturar la memoria de stack.
Para esto solo se debe agregar un nuevo constructor a la definición de la clase para permitir su creación con la memoria del heap. Por ejemplo el constructor de la clase persona seria como sigue:
Persona_c *new_Persona_inHeap(){
/* Creación de puntero a objeto persona.*/
Persona_c *punt;
/* Asignación de memoria*/
punt = (Persona_c*) malloc(sizeof(Persona_c));
if(punt == NULL){ /* Captura de error.*/
/* Gestión de error.*/
printf("No fue posible crear el objeto. Memoria insuficiente! \n");
return NULL;
}
/* Asignación de métodos de objeto persona con la vtable de la clase persona. */
punt->metodos = &vtable_Persona;
/* Inicialización por defecto de atributos del objeto. */
punt->edad= 0;
punt->altura= 0;
return punt;
}
La memoria reservada por el objeto al momento de instanciarse, debe ser liberada al finalizar la ejecución del programa, ya que de lo contrario se perderá toda referencia de la memoria utilizada por el objeto y ya no sera posible recuperarla por lo que se producirán perdidas de memoria (memory leaks). Para evitar las memory leaks es recomendable utilizar un destructor del objeto, el cual para el ejemplo de persona se podría implementar como sigue:
void delete_Persona_inHeap(Persona_c* p){
if(p != NULL) /* Si puntero no es null es posible liberar la memoria.*/
{
free(p); /* liberación de memoria previamente reservada.*/
p = NULL;
}
else { /* Captura de error, posible Unallocated.*/
/* Gestión de error*/
}
}
De esta forma los objetos instanciados utilizan la memoria del heap es por lo cual los programas son mas eficientes en la gestión de memoria. Reescribiendo los archivos de la clase persona seria como se muestra a continuación.
Archivo cabecera de la clase:
#ifndef CLASE_PERSONA_H /* protección de inclusión */
#define CLASE_PERSONA_H
typedef struct persona_struct Persona_c; /* estructura opaca de clase persona*/
/* Vtable de clase persona*/
struct p_metodos
{
int (*getEdad)(Persona_c *);
float (*getAltura)(Persona_c *);
};
/* Estructura de la clase persona*/
struct persona_struct
{
/* Atributos */
int edad;
float altura;
/* Metodos */
const struct p_metodos *metodos;
};
/* Declaración de métodos de clase persona*/
void new_Persona(Persona_c *p);
Persona_c* new_Persona_inHeap();
void delete_Persona_inHeap(Persona_c* p);
int edadPersona(Persona_c *p);
float alturaPersona(Persona_c *p);
#endif /* CLASE_PERSONA_H */
Archivo fuente de la clase:
#include <stdio.h>
#include <stdlib.h>
#include "Persona_c.h"
/* Asignación de métodos a vtable de clase persona*/
struct p_metodos vtable_Persona = {
.getEdad = edadPersona,
.getAltura = alturaPersona,
};
/* Implementación de constructores de clase Persona*/
void new_Persona(Persona_c *p){
/* Asignación de métodos de objeto persona con la vtable de la clase persona. */
p->metodos = &vtable_Persona;
/* Inicialización por defecto de atributos del objeto. */
p->edad= 0;
p->altura= 0;
}
Persona_c *new_Persona_inHeap(){
/* Creación de puntero a objeto persona.*/
Persona_c *punt;
/* Asignación de memoria*/
punt = (Persona_c*) malloc(sizeof(Persona_c));
if(punt == NULL){ /* Captura de error.*/
/* Gestión de error.*/
printf("No fue posible crear objeto! \n");
return NULL;
}
/* Asignación de métodos de objeto persona con la vtable de la clase persona. */
punt->metodos = &vtable_Persona;
/* Inicialización por defecto de atributos del objeto. */
punt->edad= 0;
punt->altura= 0;
return punt;
}
/* Implementación de destructor de clase persona. */
void delete_Persona_inHeap(Persona_c* p){
if(p != NULL) /* Si puntero no es null es posible liberar la memoria.*/
{
free(p); /* liberación de memoria previamente reservada.*/
p = NULL;
}
else { /* Captura de error, posible Unallocated.*/
/* Gestión de error*/
}
}
/* Implementación de métodos de clase Persona*/
int edadPersona(Persona_c *p){ return p->edad; }
float alturaPersona(Persona_c *p){ return p->altura; }
Uso de clases en función principal espacio usuario:
#include <stdio.h>
#include <string.h>
#include "Persona_c.h"
int main()
{
/* Creación de objeto persona con reserva de memoria en heap.*/
Persona_c *persona_1 = new_Persona_inHeap(persona_1);
printf("Edad de persona: %d \n", persona_1->metodos->getEdad(persona_1));
printf("Altura de persona: %.2f \n", persona_1->metodos->getAltura(persona_1));
/* Liberación de memoria previamente reservada.*/
delete_Persona_inHeap(persona_1);
return 0;
}
Todo esto también es valido en el espacio kernel. La definición de clases en el kernel de Linux utilizando memoria del heap se realiza de manera muy similar al espacio usuario tal como muestra el ejemplo 5.
Descarga el código fuente del ejemplo aquí.