Вы можете определенно написать C в (несколько) объектно-ориентированном стиле.
Инкапсуляция может быть выполнена путем хранения определений ваших структур в .c файле, а не в соответствующем заголовке. Затем внешний мир обрабатывает ваши объекты, сохраняя указатели на них, , и вы предоставляете функции, принимающие такие указатели, как «методы» ваших объектов.
полиморфизм типа поведения могут быть получены с помощью функции указателей, обычно группируются в «операции структур», вроде как «виртуальный метод таблицы» в вашем C++ объекты (или как там это называется). Структура ops также может включать в себя другие вещи, такие как константы, значение которых специфично для данного «подкласса». «Родительская» структура может содержать ссылку на данные, специфичные для ОП, через общий указатель void*
. Конечно, «подкласс» может повторять шаблон для нескольких уровней наследования.
Так, в приведенном ниже примере, struct printer
сродни абстрактный класс, , который может быть «производной», заполнив pr_ops
структуру, и предоставление функции конструктора оберточную pr_create()
. Каждый подтип будет иметь свою собственную структуру, которая будет «привязана» к объекту struct printer
через data
общий указатель. Это демонизируется подтипом fileprinter
. Можно представить графический интерфейс или принтер на основе сокетов, , который будет обрабатываться независимо от остальной части кода в качестве ссылки struct printer *
.
printer.h:
struct pr_ops {
void (*printline)(void *data, const char *line);
void (*cleanup)(void *data);
};
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data);
void pr_printline(struct printer *pr, const char *line);
void pr_delete(struct printer *pr);
printer.c:
#include "printer.h"
...
struct printer {
char *name;
struct pr_ops *ops;
void *data;
}
/* constructor */
struct printer *pr_create(const char *name, const struct output_ops *ops, void *data)
{
struct printer *p = malloc(sizeof *p);
p->name = strdup(name);
p->ops = ops;
p->data = data;
}
void pr_printline(struct printer *p, const char *line)
{
char *l = malloc(strlen(line) + strlen(p->name) + 3;
sprintf(l, "%s: %s", p->name, line);
p->ops->printline(p->data, l);
}
void pr_delete(struct printer *p)
{
p->ops->cleanup(p->data);
free(p);
}
Наконец, fileprinter.c:
struct fileprinter {
FILE *f;
int doflush;
};
static void filepr_printline(void *data, const char *line)
{
struct fileprinter *fp = data;
fprintf(fp->f, "%s\n", line);
if(fp->doflush) fflush(fp->f);
}
struct printer *filepr_create(const char *name, FILE *f, int doflush)
{
static const struct ops = {
filepr_printline,
free,
};
struct *fp = malloc(sizeof *fp);
fp->f = f;
fp->doflush = doflush;
return pr_create(name, &ops, fp);
}
Какова причина, что делать? –
У меня есть код C, использующий в основном контейнеровозы. Проект достиг точки, в которой заменимость («отношение») стала очень желательной. –
в основном отвечает на все ваши вопросы: [http://stackoverflow.com/questions/415452/object-orientation-in-c/415536#415536](http://stackoverflow.com/questions/415452/object-orientation-in -c/415536 # 415536) – Junier