Некоторые мысли (и этот вопрос должен быть вики сообщества)
статические
функции там, где вы в противном случае использовали бы частные
методы. static
, а также даст вам хорошее указание, когда пришло время выделить некоторые функции в отдельный файл. Для Java-программиста это не должно быть слишком странной практикой. структурирует его, как правило, таким же образом. Разделяйте вещи на несколько файлов, каждый из которых содержит код, выполняющий связанную работу.
Часто с помощью C вы все еще можете думать об объектах. Но вместо классов с методами они представляют собой структуры и функции, которые работают со структурой.
Я бы порекомендовал разделить ваш проект на более мелкие компоненты и поместить каждый компонент в отдельный файл .c и .h. Вы помещаете код в файл .c, а структуры и прототипы в файл .h.
Поступая так, вы можете программировать объектно-ориентированные программы на C, если сохраните реентерабельность ваших функций: скажем, несколько функций выполняют функцию FOO, а затем вместо глобальных переменных в foo.c объявите структура с именем FOO
в foo.h , а функции принимают указатель на структуру FOO
в качестве своего первого параметра.
То, что это C, не означает, что он не объектно-ориентированный. См. этот вопрос или любое количество вопросов, названных с некоторыми вариациями «Изучение C на основе объектно-ориентированного фона».
Подобные методы все еще используются сегодня - GIMP построен на GTK + , который включает библиотеку GObject для объектно-ориентированного кодирования на C. Возможно, это не лучший способ и, возможно, не «идиоматический» язык C, но он может вам помочь.
Другой совет. Я рассказываю, как кодировать ремонтопригодность в большом проекте использовать библиотеки. В C не так много встроенных функций, поэтому чем больше функций вы можете выжать из переносимой (с открытым исходным кодом?) Библиотеки сторонних производителей, тем меньше кода вам придется написать (и, следовательно, поддерживать).
GTK + снова имеет GLib , которая представляет собой универсальную библиотеку с множеством функций, которые люди реализуют и повторно реализуют на C. У Apache есть собственная, Apache Portable Runtime ], который делает нечто очень похожее (но с разными функциями). Есть также несколько строковых библиотек, которые, вероятно, избавят вас от головной боли, и еще несколько библиотек специального назначения (Readline для интерактивных подсказок, Ncurses для текстовых интерфейсов, таких как vi и т. Д.), Которые полезны, но могут не играть огромной роли в ваше конкретное приложение.
Лучший выбор в некоторой степени зависит от того, что вы пишете. Если вы пишете ядро операционной системы, драйвер устройства или любое приложение для встроенных систем, не обращайте внимания на все приведенные выше советы. Если ты'
Вы можете выполнять объектно-ориентированное программирование на c, например:
Несколько предложений ...
• Как можно чаще используйте модификатор static
; это (в основном) эквивалент private
в объектно-ориентированных языках.
• Старайтесь не использовать слишком много глобальных переменных, особенно если ваша программа использует несколько потоков.
• Сгруппируйте связанную информацию в ] структуры
; это ваши объекты в C.
• C не имеет обработки исключений, поэтому проверьте возвращаемые значения всех системных функций, которые вы вызываете.
OO - это просто синтаксический сахар. Исходные компиляторы C ++ скомпилированы для C. Вот базовый пример примерно того же класса в Java и C:
Point.java
import java.lang.Math;
public class Point
{
private int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int getDistance(Point p)
{
return Math.sqrt((p.x - this.x) * (p.x - this.x) + (p.y - this.y) * (p.y - this.y));
}
}
Point.h
typedef struct __Point Point;
typedef struct __Point
{
int x, y;
int (*getDistance)(Point*,Point*);
} Point;
Point* new_Point(int, int);
void delete_Point(Point*);
int getDistance(Point*, Point*);
Point.c
#include <math.h>
#include "Point.h"
Point* new_Point(int x, int y)
{
Point* this = malloc(sizeof(Point));
this->x = x;
this->y = y;
this->getDistance = getDistance;
}
void delete_Point(Point* this)
{
free(this);
}
int getDistance(Point* this, Point* p)
{
return sqrt((p->x - this->x) * (p->x - this->x) + (p->y - this->y) * (p->y - this->y));
}