ГЛАВА 4. Итерация присуща человеку, а рекурсия - богу. - Л. Дойч Все нетривиальные программы состоят из нескольких раздельно транслируемых единиц, по традиции
называемых файлами. В этой главе описано, как раздельно транслируемые функции могут вызывать
друг друга, каким образом они могут иметь общие данные, и как добиться непротиворечивости типов,
используемых в разных файлах программы. Подробно обсуждаются функции, в том числе: передача
параметров, перегрузка имени функции, стандартные значения параметров, указатели на функции и,
естественно, описания и определения функций. В конце главы обсуждаются макровозможности языка.
4.1 Введение Роль файла в языке С++ сводится к тому, что он определяет файловую область видимости ($$R.3.2).
Это область видимости глобальных функций (как статических, так и подстановок), а также глобальных
переменных (как статических, так и со спецификацией const). Кроме того, файл является традиционной
единицей хранения в системе, а также единицей трансляции. Обычно системы хранят, транслируют и
представляют пользователю программу на С++ как множество файлов, хотя существуют системы,
устроенные иначе. В этой главе будет обсуждаться в основном традиционное использование файлов.
Всю программу поместить в один файл, как правило, невозможно, поскольку программы стандартных
функций и программы операционной системы нельзя включить в текстовом виде в программу
пользователя. Вообще, помещать всю программу пользователя в один файл обычно неудобно и
непрактично. Разбиения программы на файлы может облегчить понимание общей структуры программы
и дает транслятору возможность поддерживать эту структуру. Если единицей трансляции является
файл, то даже при небольшом изменении в нем следует его перетранслировать. Даже для программ не
слишком большого размера время на перетрансляцию можно значительно сократить, если ее разбить
на файлы подходящего размера.
Вернемся к примеру с калькулятором. Решение было дано в виде одного файла. Когда вы попытаетесь
его транслировать, неизбежно возникнут некоторые проблемы с порядком описаний. По крайней мере
одно "ненастоящее" описание придется добавить к тексту, чтобы транслятор мог разобраться в
использующих друг друга функциях expr(), term() и prim(). По тексту программы видно, что она состоит
из четырех частей: лексический анализатор (сканер), собственно анализатор, таблица имен и драйвер.
Однако, этот факт никак не отражен в самой программе. На самом деле калькулятор не был
запрограммирован именно так. Так не следует писать программу. Даже если не учитывать все
рекомендации по программированию, сопровождению и оптимизации для такой "зряшной" программы,
все равно ее следует создавать из нескольких файлов хотя бы для удобства.
Чтобы раздельная трансляция стала возможной, программист должен предусмотреть описания, из
которых транслятор получит достаточно сведений о типах для трансляции файла, составляющего
только часть программы. Требование непротиворечивости использования всех имен и типов для
программы, состоящей из нескольких раздельно транслируемых частей, так же справедливо, как и для
программы, состоящей из одного файла. Это возможно только в том случае, когда описания,
находящиеся в разных единицах трансляции, будут согласованы. В вашей системе программирования
имеются средства, которые способны установить, выполняется ли это. В частности, многие
противоречия обнаруживает редактор связей. Редактор связей - это программа, которая связывает по
именам раздельно транслируемые части программы. Иногда его по ошибке называют загрузчиком.