- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
C++ - Страустрап Бьярн
Шрифт:
Интервал:
Закладка:
// file1.c: int a = 1; int f() (* /* что-то делает */ *)
// file2.c: extern int a; int f(); void g() (* a = f(); *)
a и f(), используемые g() в файле file2.c,– те же, что определены в файле file1.c. Ключевое слово extern (внешнее) указывает, что описание a в file2.c является (только) описнием, а не определением. Если бы a инициализировалось, extern было бы просто проигнорировано, поскольку описание с иницилизацией всегда является определением. Объект в программе должен определяться только один раз. Описываться он может много раз, но типы должны точно согласовываться. Например:
// file1.c: int a = 1; int b = 1; extern int c;
// file2.c: int a; extern double b; extern int c;
Здесь три ошибки: a определено дважды (int a; является определением, которое означает int a=0;), b описано дважды с разными типами, а c описано дважды, но не определено. Эти вды ошибок не могут быть обнаружены компилятором, который за один раз видит только один файл. Компоновщик, однако, их онаруживает.
Следующая программа не является С++ программой (хотя C программой является):
// file1.c: int a; int f() (* return a; *)
// file2.c: int a; int g() (* return f(); *)
Во-первых, file2.c не С++, потому что f() не была описана, и поэтому компилятор будет недоволен. Во-вторых, (когда file2.c фиксирован) программа не будет скомпонована, посколку a определено дважды.
Имя можно сделать локальным в файле, описав его static. Например:
// file1.c: static int a = 6; static int f() (* /* ... */ *)
// file2.c: static int a = 7; static int f() (* /* ... */ *)
Поскольку каждое a и f описано как static, получающаяся в результате программа является правильной. В каждом файле своя a и своя f().
Когда переменные и функции явно описаны как static, часть программы легче понять (вам не надо никуда больше залядывать). Использование static для функций может, помимо этого, выгодно влиять на расходы по вызову функции, поскольку дает оптимизирующему компилятору более простую работу.
Рассмотрим два файла:
// file1.c: const int a = 6; inline int f() (* /* ... */ *) struct s (* int a,b; *)
// file1.c: const int a = 7; inline int f() (* /* ... */ *) struct s (* int a,b; *)
Раз правило «ровно одно определение» применяется к контантам, inline-функциям и определениям функций так же, как оно применяется к функциям и переменным, то file1.c и file2.c не могут быть частями одной С++ программы. Но если это так, то как же два файла могут использовать одни и те же типы и константы? Коротко, ответ таков: типы, константы и т.п. могут определяться столько раз, сколько нужно, при условии, что они определяются одинаково. Полный ответ несколько более сложен (это объясняется в следующем разделе).
4.3 Заголовочные файлы
Типы во всех описаниях одного и того же объекта должны быть согласованными. Один из способов это достичь мог бы сотоять в обеспечении средств проверки типов в компоновщике, но большинство компоновщиков – образца 1950-х, и их нельзя измнить по практическим соображениям*. Другой подход состоит в обеспечении того, что исходный текст, как он передается на рассмотрение компилятору, или согласован, или содержит инфомацию, которая позволяет компилятору обнаружить несогласованости. Один несовершенный, но простой способ достичь согласванности состоит во включении заголовочных файлов, содержащих интерфейсную информацию, в исходные файлы, в которых содежится исполняемый код и/или определения данных.
– * Легко изменить один компоновщик, но сделав это и напсав программу, которая зависит от усовершенствований, как вы будете переносить эту программу в другое место? (прим. автра)
Механизм включения с помощью #include – это чрезвычайно простое средство обработки текста для сборки кусков исходной программы в одну единицу (файл) для ее компиляции. Директива
#include «to_be_included»
замещает строку, в которой встретилось #include, содежимым файла «to_be_included». Его содержимым должен быть иходный текст на С++, поскольку дальше его будет читать комплятор. Часто включение обрабатывается отдельной программой, называемой C препроцессором, которую команда CC вызывает для преобразования исходного файла, который дал программист, в файл без директив включения перед тем, как начать собственно компиляцию. В другом варианте эти директивы обрабатывает итерфейсная система компилятора по мере того, как они встречются в исходном тексте. Если программист хочет посмотреть на результат директив включения, можно воспользоваться командой
CC -E file.c
для препроцессирования файла file.c точно также, как это сделала бы CC перед запуском собственно компилятора. Для включения файлов из стандартной директории включения вместо кавычек используются угловые скобки « и ». Например:
#include «stream.h» //из стандартной директории включения #define «myheader.h» // из текущей директории
Использование «» имеет то преимущество, что в программу фактическое имя директории включения не встраивается (как правило, сначала просматривается /usr/include/CC, а потом usr /include). К сожалению, пробелы в директиве include сущесвенны:
#include « stream.h » // не найдет «stream.h»
Может показаться, что перекомпилировать файл заново кадый раз, когда он куда-либо включается, расточительно, но время компиляции такого файла обычно слабо отличается от врмени, которое необходимо для чтения его некоторой заранее окомпилированной формы. Причина в том, что текст программы яляется довольно компактным представлением программы, и в том, что включаемые файлы обычно содержат только описания и не сдержат программ, требующих от компилятора значительного анлиза.
Следующее эмпирическое правило относительно того, что следует, а что не следует помещать в заголовочные файлы, яляется не требованием языка, а просто предложением по разуному использованию аппарата #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 «signal.h» Определения макросов #define Case break;case Комментарии /* проверка на конец файла */
но никогда
Определения обычных функций char get() (* return *p++; *) Определения данных int a;
Определения сложных константных объектов const tbl[]=(*/* ... */ *)
В системе UNIX принято, что заголовочные файлы имеют суффикс (расширение) .h. Файлы, содержащие определение данных или функций, должны иметь суффикс .c. Такие файлы часто назвают, соответственно, «.h файлы» и «.c файлы». В #4.7 описваются макросы. Следует заметить, что в С++ макросы гораздо менее полезны, чем в C, поскольку С++ имеет такие языковые конструкции, как const для определения констант и inline для исключения расходов на вызов функции.
Причина того, почему в заголовочных файлах допускается определение простых констант, но не допускается определение сложных константных объектов, прагматическая. В принципе, сложность тут только в том, чтобы сделать допустимым дублирвание определений переменных (даже определения функций можно было бы дублировать). Однако для компоновщиков старого обраца слишком трудно проверять тождественность нетривиальных констант и убирать ненужные повторы. Кроме того, простые слчаи гораздо более обиходны и потому более важны для генерации хорошего кода.
4.3.1 Один заголовочный файл
Проще всего решить проблему разбиения программы на неколько файлов поместив функции и определения данных в подхдящее число исходных файлов и описав типы, необходимые для их взаимодействия, в одном заголовочном файле, который включаеся во все остальные файлы. Для программы калькулятора можно использовать четыре .c файла: lex.c, syn.c, table.c и main.c, и заголовочный файл dc.h, содержащий описания всех имен, кторые используются более чем в одном .c файле:

