Это зависит от того, какой именно объектно-ориентированный набор функций вы хотите иметь. Если вам нужны такие вещи, как перегрузка и / или виртуальные методы, вам, вероятно, нужно включить указатели на функции в структурах:
typedef struct {
float (*computeArea)(const ShapeClass *shape);
} ShapeClass;
float shape_computeArea(const ShapeClass *shape)
{
return shape->computeArea(shape);
}
Это позволит вам реализовать класс, «унаследовав» базовый класс и реализовав подходящую функцию:
typedef struct {
ShapeClass shape;
float width, height;
} RectangleClass;
static float rectangle_computeArea(const ShapeClass *shape)
{
const RectangleClass *rect = (const RectangleClass *) shape;
return rect->width * rect->height;
}
Это, конечно, требует от вас также реализации конструктора, который обеспечивает правильную настройку указателя на функцию. Обычно вы динамически выделяете память для экземпляра, но вы также можете позволить вызывающей стороне сделать это:
void rectangle_new(RectangleClass *rect)
{
rect->width = rect->height = 0.f;
rect->shape.computeArea = rectangle_computeArea;
}
Если вам нужно несколько разных конструкторов, вам придется «декорировать» имена функций, вы не можете иметь более одной rectangle_new()
функции:
void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
rectangle_new(rect);
rect->width = width;
rect->height = height;
}
Вот базовый пример, показывающий использование:
int main(void)
{
RectangleClass r1;
rectangle_new_with_lengths(&r1, 4.f, 5.f);
printf("rectangle r1's area is %f units square\n", shape_computeArea(&r1));
return 0;
}
Надеюсь, это даст вам хотя бы некоторые идеи. Для успешного и богатого объектно-ориентированного фреймворка в C, посмотрите библиотеку glib GObject .
Также обратите внимание, что выше не было смоделированного явного «класса», каждый объект имеет свои собственные указатели на методы, которые немного более гибки, чем вы обычно найдете в C ++. Кроме того, это стоит памяти. Вы можете избежать этого, вставив указатели методов в структуру class
, и придумать способ для каждого экземпляра объекта ссылаться на класс.