2010-09-22 25 views
29

Teniendo en cuenta:Constructor para estructuras en C

struct objStruct { 
    int id; 
    int value; 
}; 

typedef struct objStruct Object; 

¿Hay un acceso directo para asignar e inicializar el objeto, algo así como un constructor de C++?
Incluso podría ser una macro de preprocesador. Lo que hace que el código más corto y más fácil de leer que esto:

Object *newObj = malloc(sizeof(Object)); 
// successful allocation test snipped 
newObj->id = id++; 
newObj->value = myValue; 
+0

duplicado de [Constructor in C] (http://stackoverflow.com/questions/537244/constructor-in-c), [Inicializando estructuras C] (http://stackoverflow.com/questions/1994841/initialising- c-structures) – outis

+2

Ninguno de los posibles duplicados ([Constructor predeterminado en C] (http://stackoverflow.com/questions/537244/) o [Inicializando estructuras C en código C++] (http://stackoverflow.com/questions/1994841 /)) es realmente un buen duplicado para esto, aunque están relacionados. Han sido retitulados desde que se realizó el comentario anterior. –

Respuesta

36

En C normalmente se crea una función en el estilo de un constructor que hace esto. Por ejemplo (comprobación de errores omite por razones de brevedad)

Object* Object_new(int id, int value) { 
    Object* p = malloc(sizeof(Object)); 
    p->id = id; 
    p->value = value; 
    return p; 
} 

... 
Object* p1 = Object_new(id++, myValue); 
+5

Puede ser un poco exagerado, pero generalmente también creo un objStruct_destroy vacío (objStruct * obj) que me es gratis, en caso de que necesite agregar alguna liberación para las estructuras asignadas dentro de más tarde. –

+6

Sí; excepto que a veces es preferible que el "constructor" tome el Object * como un parámetro en su lugar, por lo que también puede hacer la asignación de la pila ('Object object; Object_initialise (& object);'). – Porculus

+1

Un método intermedio sería tener un Object_Init para realizar la inicialización en un objeto ya asignado (= constructor de ubicación), y Object_New para asignar e init (internamente debe llamar a Object_Init). Lo mismo debe hacerse para el "destructor". –

1

Si usted está buscando un objeto orientado a la "emulación" sobre C, recomiendo fuertemente el sistema de tipos GObject [1], que es madura y ampliamente utilizada por GTK, por ejemplo, .

GLib [2] también tiene un buen separador de sectores para objetos pequeños, actualmente utilizado por GNOME.

[1] GObject Reference Manual

[2] GLib Memory Slices

+0

Tenga en cuenta que algunas cosas que normalmente se comprueban en tiempo de compilación en C++, se realizan solo en tiempo de ejecución en GObject. – Ruslan

3
struct thingy { 
    char * label; 
    int x; 
}; 

#define declare_thingy(name, label, val) struct thingy name = { label, val } 

struct thingy * new_thingy(const char * label, int val) { 
    struct thingy * p = malloc(sizeof(struct thingy)); 
    if (p) { 
      p->label = label; 
      p->val = val; 
    } 
    return p; 
} 
20

En C99 y más allá, se puede utilizar un compuesto literal, que se parece a un molde seguido de un inicializador entre llaves:

int init_value = ...; 
int init_id = ...; 
Object newObj1 = (Object){ .value = init_value, .id = init_id }; 
Object newObj2 = (Object){ .id = init_id, .value = init_value }; 

Las dos últimas líneas logran el mismo efecto: el orden de los campos no es crítico. Eso es usando 'initializers designados', otra característica de C99. Puede crear un literal compuesto sin usar los inicializadores designados.

2

Realmente hay que distinguir la inicialización de las variables static o auto y la asignación dinámica en la cabeza. Para el primero, haga inicializadores con nombre, para el segundo una función de inicio bien especificada.

Todo lo que puede ser muy bien packed into macros le damos una fácil static/auto inicialización y algo similar a new en C++.

4

En C es posible declarar una función en línea con el mismo nombre que la estructura:

struct my 
{ 
    int a; 
}; 

inline struct my* my(int* a) 
{ 
    return (struct my*)(a); 
} 

//somewhere in code 
int num = 123; 
struct my *sample = my(&num); 
//somewhere in code 

Se ve bastante similar a ctors C++.