6 Domanda: Costruttore per le strutture in C

domanda creata a Wed, Sep 22, 2010 12:00 AM

Data:

 
struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

Esiste una scorciatoia per allocare e inizializzare l'oggetto, qualcosa come un costruttore C ++?
Potrebbe anche essere una macro per il preprocessore. Qualunque cosa rende il codice più breve e più leggibile di questo:

 
Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;
    
37
  1. duplicato di Costruttore in C , Inizializzazione delle strutture C
    2010-09-22 23: 28: 45Z
  2. Nessuno dei possibili duplicati ( Costruttore predefinito in C o Inizializzare le strutture C in codice C ++ ) è davvero un buon duplicato per questo, anche se sono correlate. Sono stati rinominati da quando è stato fatto il commento precedente.
    2014-12-22 18: 50: 00Z
6 risposte                              6                         

In C Generalmente creo una funzione nello stile di un costruttore che esegue questa operazione. Ad esempio (controllo degli errori omesso per brevità)

 
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);
    
45
2010-09-22 22: 52: 55Z
  1. Potrebbe essere un po 'eccessivo, ma di solito creo anche un vuoto objStruct_destroy (objStruct * obj) che è gratuito per me, nel caso dovessi aggiungere qualsiasi freeing per strutture allocate in seguito.
    2010-09-22 22: 56: 13Z
  2. Sì; a parte il fatto che a volte è preferibile che il "costruttore" prenda l'Oggetto * come parametro, quindi puoi anche assegnare lo stack (Object object; Object_initialise(&object);).
    2010-09-22 22: 57: 29Z
  3. Un metodo intermedio dovrebbe avere un Object_Init per eseguire l'inizializzazione su un oggetto già assegnato (= costruttore di posizionamenti) e Object_New per allocare e init (internamente dovrebbe chiamare Object_Init) . Lo stesso dovrebbe essere fatto per il "distruttore".
    2010-09-22 23: 01: 04Z
  4. Dal punto di vista di un principiante: c'è una ragione per cui stai restituendo il puntatore e non l'oggetto /struct stesso?
    2014-11-30 18: 51: 22Z
  5. @ Traubenfuchs perché significherebbe fare una copia al punto di ritorno. Potrebbe essere elided , ma ciò non è garantito.
    2016-01-05 12: 01: 59Z

In C99 e oltre, puoi usare un letterale composto, che assomiglia a un cast seguito da un inizializzatore tra parentesi:

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

Le ultime due linee raggiungono lo stesso effetto: l'ordine dei campi non è critico. Quello sta usando "inizializzatori designati", un'altra caratteristica C99. Puoi creare un letterale composto senza utilizzare gli inizializzatori designati.

    
24
2015-04-12 15: 02: 39Z

In C è possibile dichiarare una funzione inline con lo stesso nome di struttura:

 
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

Sembra molto simile ai C ++.

    
6
2015-05-27 07: 49: 49Z
 
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;
}
    
3
2010-09-22 23: 02: 23Z

Devi davvero distinguere l'inizializzazione delle variabili static o auto e l'allocazione dinamica in testa. Per il primo, fai gli inizializzatori con nome, per il secondo una funzione init ben specificata.

Tutto ciò può essere piacevole impacchettato in macro ti offre una facile intializzazione static/auto e qualcosa simile a new in C ++.

    
2
2010-09-23 06: 20: 38Z

Se stai cercando una "emulazione" orientata agli oggetti su C, raccomando vivamente il GObject Type System [1], è maturo e largamente utilizzato da GTK per esempio.

GLib [2] ha anche un simpatico allocatore di slice per piccoli oggetti, attualmente utilizzato da GNOME.

[1] Manuale di riferimento GObject

[2] GLib Memory Slices     

1
2010-09-22 22: 57: 42Z
  1. Tieni presente che alcune cose che vengono normalmente controllate in fase di compilazione in C ++, vengono eseguite solo in fase di esecuzione in GObject.
    2016-01-05 12: 27: 04Z
fonte posta Qui