Конструктор для структур в C
Дано:
struct objStruct {
int id;
int value;
};
typedef struct objStruct Object;
Есть ли ярлык для выделения и инициализации объекта, что-то вроде конструктора С++?
Это может быть даже препроцессорный макрос. Все, что делает код короче и читабельнее, чем это:
Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;
Ответы
Ответ 1
В 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);
Ответ 2
В 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. Вы можете создать составной литерал без использования назначенных инициализаторов.
Ответ 3
В 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
Он выглядит очень похоже на С++ ctors.
Ответ 4
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;
}
Ответ 5
Вам действительно нужно различать инициализацию переменных static
или auto
и динамическое распределение на голове. Во-первых, именованные инициализаторы, для второй - заданная функция init.
Все, что может быть красиво
упакованные в макросы дают вам легкую static/auto
intialization и что-то похожее на new
в С++.
Ответ 6
Если вы ищете объектно-ориентированную "эмуляцию" над C, я настоятельно рекомендую систему GObject Type System [1], она зрелая и в основном используется GTK, например.
GLib [2] также имеет хороший распределитель срезов для небольших объектов, которые в настоящее время используются GNOME.
[1] Справочное руководство GObject
[2] Метки памяти GLib