Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЗФ_ОАиП / Лекции ГГУ Скорины - Программирование.doc
Скачиваний:
179
Добавлен:
21.03.2016
Размер:
2.27 Mб
Скачать

22. Многофайловая компиляция (проекты)

Любую программу, текст которой занимает даже сотни строк, можно хранить в одном файле. Но это очень не удобно. Даже если допустить, что размер файла с программой может быть любого размера, как модифицировать и отлаживать программу, размер которой 1000 строк, а на экране видно только 20 строк? Кроме этого, при увеличении длины программы значительно увеличивается и время ее компиляции. Когда размер программы достигает некоторого предела, приходится разбивать ее на части, каждая из которых хранится отдельно – в отдельном файле.

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

Преимущества такого подхода:

  • разработку и отладку разных частей программы можно поручить разным людям;

  • программу проще и удобнее отлаживать и модифицировать;

  • ускорение в работе, ведь при запуске программы можно компилировать только те файлы, которые изменялись, для остальных можно использовать уже существующие obj-файлы (т.к. файлов может быть много, а процесс компиляции в С достаточно длинный, то это дает значительный выигрыш по времени в процессе работы). Эта последовательность действий (создание сначала объектных файлов, а затем самой программы) типична для многих компиляторов и сильно экономит время при разработке больших программ, потому что обрабатываются только измененные исходные тексты. Затем объектные файлы поступают редактору связей, и на выходе получается готовая программа.

Есть два подхода к многофайловой разработке программ на языке С.

Первый подход: нужные cpp-файлы подключать по #include ”*.cpp” к главному cpp-файлу. Но это плохой подход, т.к. он не дает третьго преимущества – просто препроцессор создает один большой файл, который весь компилируется.

Второй подход: для объединений нескольких cpp-файлов в одну программу использовать проекты. Такой подход используется во многих интегрированных средах разработки (IDE Integrated development environmentсистема программных средств, используемая программистами для разработки программ. Обычно среда разработки включает в себя: текстовый редактор, компилятор и/или интерпретатор, средства автоматизации сборки, отладчик). Это подход, который позволяет использовать все преимущества многофайловой разработки программ.

Проект – это специальный файл, в который записываются имена файлов (в нашем случае cpp-файлов), которые IDE (в нашем случае BC++) следует объединять в один исполняемый exe-файл. Имя исполняемого файла совпадает в таком случае с именем проекта, а не с именем cpp-файла, как получается при однофайловой программе.

Все необходимые для работы с файлами проектов команды включены в меню Project.

Для организации файла проекта необходимо открыть файл проекта. Для этого выполняются команды Project→Open Project…. ВС++ активизирует специальное окно «Project» в нижней части экрана и открывает окно диалога, позволяющее загрузить нужный файл проекта или создать новый с заданным именем.

Если создается новый файл проекта, окно «Project» первоначально будет пустым. Включение файлов в проект и их удаление выполняются либо через команды Project→Add item… и Project→Delete item, либо нажатием клавиш Ins и Del, в случае если курсор размещен в окне «Project». При добавлении файлов в проект открывается окно диалога, позволяющее выбрать нужный файл.

В проект можно включать не только cpp-файлы, но и obj-файлы и библиотеки (.lib). Не включаются в проект заголовочные h-файлы.

Сохранение файла проекта: Options→Save…. Надо убрать два верхних крестика, оставить только сохранение проекта.

Открыть существующий файл проекта можно и так: bc имя[.prj].

Окно «Project» упрощает переход от одного файла, включенного в проект, к другому при их редактировании. Для этого надо выделить строку с нужным именем файла в окне «Project» и нажать клавишу ENTER.

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

// === файл func.cpp ================

extern int k; // в другом файле определена эта переменнная

int sumk(int a, int b) {   return k*(a+b); }

int min(int a, int b) {   return a<b ? a : b; }

// === файл task.cpp ================

int k; // глобальная переменная

int min(int, int); // прототипы функций, определенных

int sum(int, int); // в другом файле

void main() { int x, y, z;

scanf(“%d %d”, &x, &y);

scanf(“%d”, &k);

printf(“min = %d”, min(x,y));

c = sum(x,y);

printf(“sum * %d = %d”, k, c);

}

В файле func.cpp надо использовать глобальную переменную, которая определена в файле task.cpp. Т.к. каждый файл проекта компилируется по отдельности, то при компиляции func.cpp будет ошибка компиляции «Переменная k не определена». При компиляции же файла task.cpp выдаст ошибку, что функции min() и sum() не имеют прототипов. Причина ошибок понятна: в одном файле ничего не известно про глобальную переменную k, в другом файле – про функции min() и sum().

В файле func.cpp нужно как-то указать, что переменная k существует и определена в другом файле программы. Делается это с помощью указания extern. Строка extern int k; говорит компилятору, работающему с файлом func.cpp: «Переменная k определена в другом файле. В каком – не важно. Достаточно знать, что она – типа int». Увидев слово extern, компилятор создает объектный файл, в котором сказано, что переменная k – внешняя, определена в каком-то другом файле, и ее поисками займется уже редактор связей при внешнем связывании.

Нужно четко понимать, что жизнь дается переменной один раз. В нашем случае это делается в файле task.cpp, где объявление int k; велит компилятору выделить участок памяти для целочисленной переменной и заслать туда ее начальное значение 0. Слово extern ничего не создает и памяти никакой не выделяет.

Для того, чтобы указать компилятору, что какая-либо функция определена в программе, достаточно в нужном файле просто указать прототип нужной функции: int min(int,int); int sum(int,int);. Т.е. при многофайловой компиляции действуют обычные правила объявления функции, если функция не определена до момента своего использования.

Словом extern необходимо помечать только переменные. Для функций это можно не делать, потому что компилятор и так считает все функции внешними. Но чтобы указать компилятору, что функция определена в другом файле, ее прототип также можно предварить словом extern: extern int min(int,int);