Особенности работы с многофайловыми проектами

Лабораторная работа №13. Модули. Многофайловые проекты

Цель и порядок работы

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

Порядок выполнения работы:

- ознакомиться с описанием лабораторной работы;

- получить задание у преподавателя, согласно своему варианту;

- написать программу и отладить ее на ЭВМ;

- оформить отчет.

Краткая теория

Особенности работы с многофайловыми проектами

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

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

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

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

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

Исходные тексты совокупности функций для решения какой-либо подзадачи, как правило, размещаются в отдельном модуле (файле). Такой файл называют исходным (sources). Обычно он имеет расширение .c или .cpp Прототипы всех функций исходного файла выносят в отдельный так называемый заголовочный файл (header file), для него принято использовать расширение .h или .hpp.

Таким образом, заголовочный файл xxx.h содержит интерфейс для некоторого набора функций, а исходный файл ххх.срр содержит реализацию этого набора. Если некоторая функция из указанного набора вызывается из какого-то другого исходного модуля ууу.срр, то обязаны включить в этот модуль заголовочный файл xxx.h с помощью директивы #include. Негласное правило стиля программирования на C++ требует включения этого же заголовочного файла (с помощью #include) и в исходный файл ххх.срр.

Хотя использование глобальных переменных считается дурным тоном в программировании, иногда возникают ситуации когда невозможно избежать их использования. В многофайловом проекте возможны два «вида глобальности переменных». Если некоторая глобальная переменная glvar1 объявлена в файле ххх.срр с модификатором static, то она видима от точки определения до конца этого файла, то есть области видимости ограничена файлом. Если же другая глобальная переменная glvar2 объявлена в файле ххх.срр без модификатора static, то она может быть видимой в пределах всего проекта. Правда, для того, чтобы она оказалась видимой в другом файле, необходимо в этом файле ее объявление с модификатором extern (рекомендуется это объявление поместить в файл xxx.h).

В заголовочном файле принято размещать:

- определения типов, задаваемых пользователем, констант, шаблонов;

- объявления (прототипы) функций;

- объявления внешних глобальных переменных (с модификатором extern);

- пространства имен.

При подобно использовании заголовочных файлов возникает проблема их повторного включения. Проблема может возникнуть при иерархическом проектировании структур данных, когда в некоторый заголовочный файл ууу.h включается при помощи директивы include другой заголовочный файл xxx.h (например, для использования типов, определенных в этом файле) и где-нибудь еще, например в основной программе.

Для решения этой проблемы рекомендуется использовать так называемые стражи включения. Данный способ состоит в следующем: чтобы предотвратить заголовочных файлов, содержимое каждого .h файла должно находиться между директивами условной компиляции #ifndef #endif, а внутри устанавливаться признак включения при помощи директивы #define.

#ifndef FILENAME_H

#define FILENAME_H

/* содержимое заголовочного файла */

#endif

Наши рекомендации