|
||||
|
4.3.2 Множественные Заголовочные Файлы Стиль разбиения программы с одним заголовочным файлом наиболее пригоден в тех случаях, когда программа невелика и ее части не предполагается использовать отдельно. Поэтому то, что невозможно установить, какие описания зачем помещены в заголовочный файл, несущественно. Помочь могут комментарии. Другой способ – сделать так, чтобы каждая часть программы имела свой заголовочный файл, в котором определяются предотавляемые этой частью средства. Тогда каждый .c файл имеет соответствующий .h файл, и каждый .c файл включает свой собтвенный (специфицирующий то, что в нем задается) .h файл и, возможно, некоторые другие .h файлы (специфицирующие то, что ему нужно). Рассматривая организацию калькулятора, мы замечаем, что error() используется почти каждой функцией программы, а сама использует только «stream.h». Это обычная для функции ошибок ситуация, поэтому error() следует отделить от main(): // error.h: обработка ошибок extern int no_errors; extern double error(char* s); // error.c #include «stream.h» #include «error.h» int no_of_errors; double error(char* s) (* /* ... */ *) При таком стиле использования заголовочных файлов .h файл и связанный с ним .c файл можно рассматривать как мдуль, в котором .h файл задает интерфейс, а .c файл задает реализацию. Таблица символов не зависит от остальной части калькулятора за исключением использования функции ошибок. Это можно сделать явным: // table.h: описания таблицы имен struct name (* char* string; name* next; double value; *); extern name* look(char* p, int ins = 0); inline name* insert(char* s) (* return look(s,1); *) // table.c: определения таблицы имен #include «error.h» #include «string.h» #include «table.h» const TBLSZ = 23; name* table[TBLSZ]; name* look(char* p; int ins) (* /* ... */ *) Заметьте, что описания функций работы со строками теперь включаются из «string.h». Это исключает еще один возможный источник ошибок. // lex.h: описания для ввода и лексического анализа enum token_value (* NAME, NUMBER, END, PLUS='+', MINUS='-', MUL='*', DIV='/', PRINT=';', ASSIGN='=', LP='(', RP=')' *); extern token_value curr_tok; extern double number_value; extern char name_string[256]; extern token_value get_token(); Этот интерфейс лексического анализатора достаточно бепорядочен. Недостаток в надлежащем типе лексемы обнаруживает себя в необходимости давать пользователю get_token() фактческие лексические буферы number_value и name_string. // lex.c: определения для ввода и лексического анализа #include «stream.h» #include «ctype.h» #include «error.h» #include «lex.h» token_value curr_tok; double number_value; char name_string[256]; token_value get_token() (* /* ... */ *) Интерфейс синтаксического анализатора совершенно прозрчен: // syn.c: описания для синтаксического анализа и вычисления extern double expr(); extern double term(); extern double prim(); // syn.c: определения для синтаксического анализа и // вычисления #include «error.h» #include «lex.h» #include «syn.h» double prim() (* /* ... */ *) double term() (* /* ... */ *) double expr() (* /* ... */ *) Главная программа, как всегда, тривиальна: // main.c: главная программа #include «stream.h» #include «error.h» #include «lex.h» #include «syn.h» #include «table.h» #include «string.h» main(int argc, char* argv[]) (* /* ... */ *) Сколько заголовочных файлов использовать в программе, зависит от многих факторов. Многие из этих факторов сильнее связаны с тем, как ваша система работает с заголовочными фалами, нежели с С++. Например, если в вашем редакторе нет средств, позволяющих одновременно видеть несколько файлов, использование большого числа файлов становится менее привлкательным. Аналогично, если открывание и чтение 10 файлов по 50 строк в каждом требует заметно больше времени, чем чтение одного файла в 500 строк, вы можете дважды подумать, прежде чем использовать в небольшом проекте стиль множественных зголовочных файлов. Слово предостережения: набор из десяти зголовочных файлов плюс стандартные заголовочные файлы обычно легче поддаются управлению. С другой стороны, если вы разбили описания в большой программе на логически минимальные по рамеру заголовочные файлы (помещая каждое описание структуры в свой отдельный файл и т.д.), у вас легко может получиться нразбериха из сотен файлов. |
|
||