Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа4.doc
Скачиваний:
5
Добавлен:
30.11.2018
Размер:
130.05 Кб
Скачать

Несколько слов о заголовочных файлах

Заголовочный файл предоставляет место для всех extern-объявлений объектов, объявлений функций и определений встроенных функций. Это называется локализацией объявлений. Те исходные файлы, где объект или функция определяется или используется, должны включать заголовочный файл.

Пример с addToken() имеет следующий заголовочный файл:

// ----- token.h -----

typedef unsigned char uchar;

const uchar INLINE = 128;

// ...

const uchar IT = ...;

const uchar GT = ...;

extern uchar lastTok;

extern int addToken( uchar );

inline bool is_relational( uchar tok )

{ return (tok >= LT && tok <= GT); }

// ----- lex.C -----

#include "token.h"

// ...

// ----- token.C -----

#include "token.h"

// ...

При проектировании заголовочных файлов нужно учитывать несколько моментов. Все объявления такого файла должны быть логически связанными. Если он слишком велик или содержит слишком много не связанных друг с другом элементов, программисты не станут включать его, экономя на времени компиляции. Для уменьшения временных затрат в некоторых реализациях С++ предусматривается использование предкомпилированных заголовочных файлов. В руководстве к компилятору сказано, как создать такой файл из обычного. Если в вашей программе используются большие заголовочные файлы, применение предкомпиляции может значительно сократить время обработки. Чтобы это стало возможным, заголовочный файл не должен содержать объявлений встроенных (inline) функций и объектов. Любая из следующих инструкций является определением и, следовательно, не может быть использована в заголовочном файле:

extern int i = 10;

double fica_rate;

extern void dummy () {}

Хотя переменная i объявлена с ключевым словом extern, явная инициализация превращает ее объявление в определение. Точно так же и функция dummy(), несмотря на явное объявление как extern, определяется здесь же: пустые фигурные скобки содержат ее тело. Переменная fica_rate определяется и без явной инициализации: об этом говорит отсутствие ключевого слова extern. Включение такого заголовочного файла в два или более исходных файла одной программы вызовет ошибку связывания – повторные определения объектов.

Обычно включаемые файлы обычно содержат только описания и не содержат программ, требующих от компилятора значительного анализа.

Следующее эмпирическое правило относительно того, что следует, а что не следует помещать в заголовочные файлы, является не требованием языка, а просто предложением по разумному использованию аппарата #include. В заголовочном файле могут содержаться:

Определения типов

struct point { int x, y; }

Описания функций

Extern int strlen(const char*);

Определения inline-функций

inline char get() { return *p++; }

Описания данных

Extern int a;

Определения констант

const float pi = 3.141593

Перечисления

enum bool { false, true };

Директивы include

#include

Определения макросов

#define Case break;case

Комментарии

/* проверка на конец файла */

но никогда

Определения обычных функций

char get() { return *p++; }

Определения данных

int a;

Определения сложных константных объектов

const tbl[] = { /* ... */ }

В предыдущих примерах .c и .h файлы вместе определяли часть программы. Файл .h является интерфейсом, который используют другие части программы; .c файл задает реализацию. Такой объект часто называют модулем. Доступными делаются только те имена, которые необходимо знать пользователю, остальные скрыты. Это качество часто называют скрытием данных, хотя данные - лишь часть того, что может быть скрыто. Модули такого вида обеспечивают большую гибкость. Например, реализация может состоять из одного или более .c файлов, и в виде .h файлов может быть предоставлено несколько интерфейсов. Информация, которую пользователю знать не обязательно, искусно скрыта в .c файлах. Если важно, что пользователь не должен точно знать, что содержится в .c файлах, не надо делать их доступными в исходом виде. Достаточно эквивалентных им выходных файлов компилятора (.o файлов).

Сколько заголовочных файлов использовать в программе, зависит от многих факторов. Многие из этих факторов сильнее связаны с тем, как ваша система работает с заголовочными файлами, нежели с C++. Например, если в вашем редакторе нет средств, позволяющих одновременно видеть несколько файлов, использование большого числа файлов становится менее привлекательным. Аналогично, если открывание и чтение 10 файлов по 50 строк в каждом требует заметно больше времени, чем чтение одного файла в 500 строк, вы можете дважды подумать, прежде чем использовать в небольшом проекте стиль множественных заголовочных файлов. Слово предостережения: набор из десяти заголовочных файлов плюс стандартные заголовочные файлы обычно легче поддаются управлению. С другой стороны, если вы разбили описания в большой программе на логически минимальные по размеру заголовочные файлы (помещая каждое описание структуры в свой отдельный файл и т.д.), у вас легко может получиться неразбериха из сотен файлов.

Наверное, вы считали, что интерфейс класса полностью определяется объявлением класса, но в действительности любой класс может иметь несколько разных интерфейсов в зависимости от клиента.

  • Класс и его друзья видят один интерфейс, включающий всех членов класса и всех защищенных и открытых членов его базовых классов.

  • Производные классы видят только защищенных и открытых членов класса и его базовых классов.

  • Все остальные клиенты видят только открытых членов класса и его базовых классов.

  • Если указатель на объект преобразуется к указателю на его базовый класс, интерфейс ограничивается только открытыми членами базового класса.

Открытые, закрытые и защищенные члены; открытое и закрытое наследование; полиморфизм и дружба

— все это лишь грубые синтаксические приближения более общей концепции дизайна: один объект может иметь много специализированных интерфейсов.

Таким образом, подобная организация программы обеспечивает модульность библиотеки, необходимую для сокрытия данных от пользователей, в то же время позволяя без ошибок скомпилировать и связать нужные файлы в одну программу.