Как эффективно структурировать программу C
Позвольте мне сначала сказать, что у меня есть достаточный опыт в C и С++. Тем не менее, я начинаю новый проект в C, и я так долго работал в объектно-ориентированных языках (С# и С++), что у меня возникают проблемы с эффективным способом инкапсуляции функциональности на процедурный язык. Моя первая мысль состояла в том, чтобы просто вернуться к моим знаниям OO и структурировать что-то вроде:
struct Foo
{
int x;
char *y;
};
struct Foo *new_Foo()
{
return (struct Foo *)malloc(sizeof(struct Foo));
}
void Foo_member_function(struct Foo *foo, int z)
{
foo->x = z;
}
Но это просто кажется утомительным и противоречащим духу C. Не говоря уже о том, что это плохой человек.
Эта программа в конечном итоге станет довольно значительной, поэтому очень важно создать хорошую организацию дизайна. Я полагаю, что с годами развития в C некоторые шаблоны проектирования разработали, как наилучшим образом структурировать код для ремонтопригодности. Как и функциональное программирование, я надеюсь, что процедурное программирование имеет парадигму, которая чиста и достаточно читаема.
Указатели соответствующих статей и книг также приемлемы.
Ответы
Ответ 1
Это довольно нормальная и разумная практика. Но постарайтесь не раскрывать структуру структуры в файлах заголовков, чтобы у вас была определенная гибкость в том, как она реализована и лучше управляет вашими зависимостями.
Подробнее см. Opaque pointer.
Ответ 2
Что вы предлагаете, так это то, как я всегда писал программы C в те дни, когда я это делал. Я не думаю, что это "бедные мужчины ОО", я думаю, что это разумная процедура процедурного программирования.
Я бы заметил пару вещей о вашем коде на C:
- используйте typedefs с определениями struct, поэтому вам не нужно разбрасывать ключевое слово 'struct' на протяжении всего кода
- используют только приведения, когда они на самом деле нужны, - приведение значения возвращаемого значения из malloc() не требуется
Ответ 3
Хммм... Раньше мы использовали соглашения об именах... Ergo: str * делает что-то с общей структурой данных? Так что, возможно, просто возьмите синтаксис С# и s/./_/g?
- foo_constructor
- foo_destructor
- foo_someMethod
- foo_someMethod2//не перегружает в ANSI C
- foo_otherMethod
... и наследования нет...
- foo2_constructor
- foo2_destructor
- foo2_someMethod//и нет никакого полиморфизма
Но посмотрите на яркую сторону... вы можете использовать pointer-to-pointer-to-pointer-to-function-return-a-pointer-to-pointer-int! О, радость!
Мое самое лучшее пособие - выучить уроки Java (и путем вывода С#) и структурировать ваши библиотеки, чтобы НЕ иметь побочные эффекты... больше typdefs == меньше головных болей... и если ваша разработка, как следовать этот мудрец посоветуйте, пожалуйста, дайте мне знать; -)
Приветствия. Кит.
Ответ 4
Это довольно разумный способ написать программу на C. Существует еще одно большое приложение, которое делает практически то же самое, что и ядро Linux. Некоторые почти OO-функции, используемые там:
- структуры и операции над структурами для инкапсуляции, как в вашем примере
- указывает на базовые структуры как на вид наследования бедных людей - вы найдете множество
ссылки на struct kobject там
- макросы для генерации функций в качестве замены для программирования шаблонов
Ответ 5
C был языком низкого уровня, и в этом отношении было бы очень полезно организовать ваши структуры данных в соответствии с вашими кодовыми функциями и модулями.
Я бы предположил, что вы используете typedefs и перечисления везде, где бы вы хотели создать объекты данных. Используйте макросы или статические функции для инициализации, выделения и "уничтожения" по мере необходимости.
Ответ 6
Я согласен с приведенными выше предложениями. Вы делаете это наилучшим образом. Если вы хотите запрограммировать на C.
Конечно, вы могли бы написать предварительный процессор, чтобы автоматически генерировать эти объявления и вещи для вас.. может быть, использовать объявление "Class"... поставить функции, которые вы хотите быть функциями-членами внутри класса.. и т.д.
Но у нас есть простой компилятор С++ to C. Почему бы просто не программировать на С++, использовать настоящий компилятор С++, использовать чистые интерфейсы и просто связать код С++ с кодом C? В чем причина того, что вам нужно кодировать в C или С++? Или, если вам нужно, сгенерировать код C из компилятора и скомпилировать код вывода C вместе с тем, что вам нужно.
Ответ 7
Я работаю над проектом на некоторое время, когда библиотека должна быть на C, но я хочу иметь какую-то функциональность OO. Я делаю что-то похожее на это немного подробнее.
struct klass {
char * value;
void (*set_value) (struct klass *, const char *);
void (*destroy) (struct klass *);
};
static void
klass_method_set_value (struct klass * k, const char * value) {
if (k->value == NULL) {
}
}
static void
klass_object_desetroy (struct klass * k) {
free (k);
k = NULL;
}
static void
klass_method_destroy (struct klass * k) {
klass_object_destroy (k);
}
static struct klass *
klass_object_init (void) {
struct klass * obj = (struct klass *) malloc (sizeof (struct klass*) );
/* members */
obj->value = NULL;
/* methods */
obj->set_value = klass_method_set_value;
obj->destroy = klass_method_destroy;
return obj;
}
struct klass *
klass_new (void) {
return klass_object_init ();
}
Прости меня, если что-то не так; написал это немного быстро.