2 семестр / Литература / Язык программирования С++. Краткий курс. Страуструп
.pdf3 Модульность
-
Не прерывайте меня,
пока я прерываю вас.
+ + + + +
Уинстон Черчилль
Введение Раздельная компиляция
Модули (С++20)
Пространства имен
Обработка ошибок Исключения
+
Инварианты Альтернативные варианты обработки ошибок Контракты Статические проверки
Арrументы и возвращаемые значения функций
Передача аргументов
+
Возврат значения
Структурное связывание Советы
3.1.
Введение
Программа
на
языке
программирования
С++
состоит
из
множества
от
дельно
разработанных
частей,
таких
как
функции
(§
1.2.1
),
пользовательские
типы
(глава
2,
"Пользовательские
типы"),
иерархии
классов
(§4.5)
и
шаблоны
(глава
6,
"Шаблоны").
Ключом
к
управлению
всеми
этими
частями
является
четкое
определение
взаимодействия
между
ними.
Первым
и
самым
важным
шагом
является
разграничение
интерфейса
части
и
ее
реализации.
На
уров
не
языка
С++
представляет
интерфейсы
с
помощью
объявлений. Объявление
определяет
все,
что
необходимо
для
использования
функции
или
типа.
На
пример:
54 |
Глава 3. Модульность |
|
/ / |
Vector. срр: |
|
#include "Vector.h" |
|
|
Vector::Vector(int s) |
|
|
|
:elem{new douЬle[s]), |
sz{s) |
/ / |
Интерфейс Vector |
// |
Определение конструктора |
//Инициализация членов |
douЬle& |
Vector::operator[] |
|
{ |
|
|
return |
elem[i]; |
(int
i)
//Определение
оператора
индекса
int |
Vector::size() |
|
return sz; |
11
Определение
size()
Код
в
user.
срр
и
Vector.
срр
совместно
использует
информацию
интер
фейса
Vector,
представленную
в
Vector.
h,
но
в
остальном
эти
два
файла
независимы и могут быть скомпилированы отдельно. Графически программы могут быть представлены следующим образом.
фрагменты
Vector.h:
интерфейс
Vector
user .срр: |
|
linclude |
"Vector.h" |
использует Vector |
Vector. срр: |
|
linclude |
"Vector.h" |
определяет Vector |
Строго
говоря,
использование раздельной
компиляции
не
является
языко
вым
вопросом;
это
вопрос
о
том,
как
лучше
всего
использовать
конкретную
реализацию
языка.
Однако
он
имеет
большое
практическое
значение.
Наи
лучший
подход
к
организации
программы
состоит
в
том,
чтобы
рассматри
вать
программу
как
набор
модулей
с
точно
определенными
зависимостями,
логически
представить
модульность
с
помощью
языковых
средств,
а
затем
использовать
физическую
модульность
с
помощью
файлов для
эффективной
раздельной компиляции.
Файл. срр, компилируемый
сам
по
себе
(включая
файлы.
h,
которые
он
включает
с
помощью
директивы
iinclude),
именуется
единицей
трансля
ции.
Программа
может
состоять
из
многих
тысяч
единиц
трансляции.
56 |
Глава |
3. Модульность |
|
Vector::Vector(int s) |
|
||
|
:elem{new |
douЬle[s] }, |
sz{s} |
11
Инициализация
членов
douЬle& |
Vector::operator[] |
|
1 |
|
elem[i]; |
return |
(int
i)
int
Vector::size()
return
sz;
export
int
size
(const Vector& v) |
{ |
return
v.
size
();
}
Здесь определен модуль с именем Vector, который экспортирует
Vector, все его функции-члены, а также свободную функцию size ().
класс
Способ
применения
модулей
состоит
в
их
импорте
при
необходимости.
Например:
11 |
Файл |
user.cpp: |
import |
Vector; |
// Получение |
#include <cmath> |
//Интерфейс |
|
douЫe |
sqrt_sum(Vector& v) |
1 |
sum = |
|
douЫe |
О; |
|
for(int |
i=O; |
i!=v.size(); |
sum+=std::sqrt(v[i]); |
||
return |
sum; |
|
интерфейса Vector |
|
|
математических функций, |
включая |
|
++i) |
|
|
//Сумма квадратных |
корней |
sqrt()
Я
мог
бы
импортировать
и
математические
функции
стандартной
библио
теки,
но
я
использовал
старомодный
#include,
чтобы
показать,
что
вы
може
те
смешивать
старые
и
новые
директивы
в
одной
программе.
Такое
смешение
необходимо
для постепенного
перевода
старого
кода
с
#include
на
import.
Различие
между
заголовочными
файлами
и
модулями
не
просто
синтакси
ческое.
•
•
•
Модуль компилируется только один раз (а |
не |
в каждой единице трансля |
|
ции, в которой он используется). |
|
|
|
Два модуля могут импортироваться в любом |
порядке без изменения их |
||
смысла. |
|
|
|
Если вы импортируете нечто в модуль, то |
пользователи этого модуля не |
||
получают неявный доступ к тому, что |
вы |
импортируете (и импортиро |
|
ванные сущности никак не влияют на |
вашу работу): import не являет |
ся
транзитивным.