2010-09-22 205 views
29

結構考慮:構造在C

struct objStruct { 
    int id; 
    int value; 
}; 

typedef struct objStruct Object; 

是否有一個快捷方式來分配和初始化對象,有點像C++的構造函數?
它甚至可能是一個預處理宏。無論什麼使代碼更短,更易讀:

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

[C中的構造函數]的副本(http://stackoverflow.com/questions/537244/constructor-in-c),[初始化C結構](http://stackoverflow.com/questions/1994841/initialising- c結構) – outis 2010-09-22 23:28:45

+2

沒有可能的重複項([C中的默認構造函數](http://stackoverflow.com/questions/537244/)或[在C++代碼中初始化C結構](http://stackoverflow.com/questions/1994841 /))對此非常重要,儘管它們是相關的。自上次發表評論以來,它們已被重新命名。 – 2014-12-22 18:50:00

回答

36

在C中,我通常創建一個函數的構造函數,這樣做。例如(檢查略去了錯誤)

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

這可能有點矯枉過正,但我​​通常也會創建一個void objStruct_destroy(objStruct * obj),它對我來說是免費的,以防以後需要爲分配的結構添加任何空閒。 – 2010-09-22 22:56:13

+6

是;除了有時最好讓「構造函數」把Object *當作一個參數來代替,所以你也可以做堆棧分配('Object object; Object_initialise(&object);')。 – Porculus 2010-09-22 22:57:29

+1

中間方法將有一個Object_Init對已經分配的對象(=放置構造函數)執行初始化,Object_New分配和init(在內部它應該調用Object_Init)。對於「析構函數」也應該這樣做。 – 2010-09-22 23:01:04

1

如果您正在尋找爲本「仿真」對C的對象,我強烈建議GObject的類型系統[1],它的成熟,主要是使用GTK例如。對於GNOME目前使用的小對象,GLib [2]也有一個很好的slice分配器。

[1] GObject Reference Manual

[2] GLib Memory Slices

+0

檢查錯誤請注意,雖然通常在C++編譯時檢查的某些內容僅在運行時在GObject中完成。 – Ruslan 2016-01-05 12:27:04

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

在C99及以後,可以用文字的化合物,其看起來像一個鑄造,隨後在大括號的初始化:

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

後兩條線達到同樣的效果 - 字段的順序並不重要。這是使用'指定初始化器',另一個C99功能。您可以創建複合文字而不使用指定的初始值設定項。

2

你真的必須區分staticauto變量的初始化和頭部的動態分配。對於第一個,執行命名的初始化器,第二個是指定的初始化函數。

所有可以很好地 packed into macros給你做一個簡單的static/auto intialization和類似new東西在C++。

4

在C有可能用相同的名稱作爲結構聲明一個內聯函數:

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 

它看起來很類似於C++構建函數。