Расположение объявлений и определений функций

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

В небольших программах допускается объявление функции не указывать, при условии, что определение функции расположено перед функцией main() (листинг 12.2). Кстати, функция main() также не требует объявления, так как она вызывается первой.

Листинг 12.2. Расположение определения функции перед функцией main()

#include <iostream>

int sum_i(int x, int y) {
   return x + y;
}
int main() {
   int z = sum_i(10, 20);
   std::cout << "z = " << z << std::endl; // z = 30
   return 0;
}

При увеличении количества функций возникает ситуация, когда внутри функции вызывается вторая функция, а внутри второй вызывается третья и т. д. В результате приходится решать вопрос: что было раньше курица или яйцо? Чтобы избежать такой ситуации объявления функций следует размещать в начале программы перед функцией main(), а определения — после функции main() (листинг 12.3). В этом случае порядок следования определений функций не имеет значения.

Листинг 12.3. Расположение объявлений и определений функций

#include <iostream>

int sum_i(int, int);        // Объявление

int main() {
   int z = sum_i(10, 20);
   std::cout << "z = " << z << std::endl; // z = 30
   return 0;
}
int sum_i(int x, int y) {   // Определение
   return x + y;
}

При увеличении размера программы объявлений и определений функций становится все больше и больше. В этом случае программу разделяют на несколько отдельных файлов. Объявления функций выносят в заголовочный файл с расширением hpp (или с расширением h), а определения функций размещают в одноименном файле с расширением cpp (или с расширением c в языке C). Все файлы располагают в одном каталоге с основным файлом, содержащим функцию main(). В дальнейшем с помощью директивы #include подключают заголовочный файл во всех остальных файлах. Если в директиве #include название заголовочного файла указывается внутри угловых скобок, то поиск файла осуществляется в путях поиска заголовочных файлов. Если название указано внутри кавычек, то поиск вначале производится в каталоге с основным файлом, а затем в путях поиска заголовочных файлов.

В качестве примера вынесем функцию sum_i() в отдельный файл (например, с названием my_module.cpp), а затем подключим его к основному файлу. Для создания файла my_module.cpp в окне Project Explorer щелкаем правой кнопкой мыши на названии каталога src и из контекстного меню выбираем пункт New | Source File (см. рис. 2.2). В открывшемся окне (см. рис. 2.4) в поле Source folder должно быть уже вставлено значение, например, Test64/src. В поле Source file вводим my_module.cpp, а из списка Template выбираем пункт <None>. Нажимаем кнопку Finish.

В результате файл будет добавлен в каталог проекта и его название отобразится в окне Project Explorer, а сам файл будет открыт на отдельной вкладке. Вставляем в этот файл код из листинга 12.4.

Листинг 12.4. Файл my_module.cpp

#include "my_module.hpp"

int sum_i(int x, int y) { // Определение
   return x + y;
}

Для создания файла my_module.hpp в окне Project Explorer щелкаем правой кнопкой мыши на названии каталога src и из контекстного меню выбираем пункт New | Header File (см. рис. 2.2). В открывшемся окне (см. рис. 2.6) в поле Source folder должно быть уже вставлено значение, например, Test64/src. В поле Header file вводим my_module.hpp, а из списка Template выбираем пункт Default C++ header template. Нажимаем кнопку Finish.

В результате файл будет добавлен в каталог проекта и его название отобразится в окне Project Explorer, а сам файл будет открыт на отдельной вкладке. Вставляем в этот файл код из листинга 12.5.

Листинг 12.5. Файл my_module.hpp

#ifndef MY_MODULE_HPP_
#define MY_MODULE_HPP_

#include <iostream>
int sum_i(int, int);        // Объявление функции

#endif /* MY_MODULE_HPP_ */

Все содержимое файла my_module.hpp расположено внутри условия, которое проверяется перед компиляцией. Условие выглядит следующим образом:

#ifndef MY_MODULE_HPP_
// Инструкции
#endif /* MY_MODULE_HPP_ */

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

#define MY_MODULE_HPP_

Вместо этих директив можно указать в самом начале заголовочного файла директиву препроцессора #pragma со значением once, которая также препятствует повторному включению файла:

#pragma once
// Объявление функций и др.

Теперь, чтобы использовать функцию sum_i(), достаточно подключить файл my_module.hpp к основной программе. Пример подключения приведен в листинге 12.6.

Листинг 12.6. Основная программа

#include "my_module.hpp"

int main() {
   int z = sum_i(10, 20);
   std::cout << "z = " << z << std::endl; // z = 30
   return 0;
}

В директиве #include допускается указывать не только название файла, но и абсолютный или относительный путь к нему. Это позволяет размещать файлы по различным каталогам. Примеры указания абсолютного и относительного пути:

#include "C:\\cpp\\projects\\Test64\\src\\my_module.hpp"
#include "C:/cpp/projects/Test64/src/my_module.hpp"
#include "/cpp/projects/Test64/src/my_module.hpp"
#include "folder/my_module.hpp"

При использовании больших программ создают статическую (файлы с расширением lib в VC++ или с расширением a в MinGW) или динамическую (файлы с расширением dll в Windows) библиотеку. Статические библиотеки становятся частью программы при компиляции, а динамические библиотеки подгружаются при запуске программы. Процесс создания библиотек мы будем изучать в главе 24.

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов