C++ (Хилл, Страуструп) - страница 73

Поскольку каждое 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 вызывает для преобразования исходного файла, который дал программист, в файл без директив включения перед тем, как начать собственно компиляцию. В другом варианте эти директивы обрабатывает итерфейсная система компилятора по мере того, как они встречются в исходном тексте. Если программист хочет посмотреть на результат директив включения, можно воспользоваться командой