cpp

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

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

В небольших программах допускается объявление функции не указывать, при условии, что определение функции расположено перед функцией 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. Все файлы располагают в одном каталоге с основным файлом, содержащим функцию main(). В дальнейшем с помощью директивы #include подключают заголовочный файл во всех остальных файлах. Если в директиве #include название заголовочного файла указывается внутри угловых скобок, то поиск файла осуществляется в путях поиска заголовочных файлов. Если название указано внутри кавычек, то поиск вначале производится в каталоге с основным файлом, а затем в путях поиска заголовочных файлов.

В качестве примера вынесем функцию sum_i() в отдельный файл (например, с названием my_module.cpp), а затем подключим его к основному файлу. Добавляем файл с программой согласно инструкциям из разд. 2.3. На втором шаге мастера (см. рис. 2.5) в поле Имя файла указываем название my_module.cpp.

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

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

#include "my_module.hpp"

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

Для создания заголовочного файла my_module.hpp выполняем инструкции из разд. 2.4. На втором шаге мастера (см. рис. 2.8) в поле Имя файла указываем название my_module.hpp. В результате файл будет добавлен в каталог проекта и его название отобразится на вкладке Проекты, а сам файл будет открыт на отдельной вкладке. Вставляем в этот файл код из листинга 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\\projectsQt\\Test64\\my_module.hpp"
#include "C:/cpp/projectsQt/Test64/my_module.hpp"
#include "folder/my_module.hpp"

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

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

Помощь сайту

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

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

cpp