Перейти к содержимому
Теория · Сборка и препроцессор · урок 1 из 7

Заголовки и единицы трансляции

Функцию triple определяют в triple.cpp, а вызывают из main.cpp, report.cpp и других файлов программы. Компилятор (compiler) примет каждый вызов, только если выше него стоит объявление (declaration) int triple(int x);. Копировать это объявление в каждый файл вручную ненадёжно. Если тип параметра (parameter) поменяют в одной копии и забудут про остальные, файлы начнут объявлять разные функции.

Заголовочный файл

Объявление пишут один раз, в заголовочном файле (header) — файле с объявлениями, который подключают туда, где они нужны. Файл main.cpp подключает его директивой #include:

C++
#include <iostream>
#include "triple.h"

int main() {
    std::cout << triple(14) << '\n';  // 42
}

Директива #include вставляет на своё место текст заголовка triple.h, а в нём одна строка — объявление:

C++
int triple(int x);

Имя своего заголовка пишут в кавычках, а заголовка стандартной библиотеки — в угловых скобках. Заголовок обычно называют так же, как .cpp-файл с определениями (definitions). Определение остаётся в triple.cpp, и этот файл тоже подключает triple.h:

C++
#include "triple.h"

int triple(int x) {
    return x * 3;
}

Теперь объявление и определение стоят в одном файле. Если они разойдутся по типу результата, компилятор сообщит об ошибке ещё при компиляции triple.cpp.

Единица трансляции

Компилятор переводит не отдельный файл, а единицу трансляции (translation unit): .cpp-файл вместе со всем текстом, который вставили в него директивы #include. Каждую единицу он компилирует отдельно, в свой объектный файл (object file). Заголовок сам по себе не компилируется: его текст входит в каждую единицу, которая его подключила. Поэтому в команде сборки (build) перечисляют только .cpp-файлы: clang++ main.cpp triple.cpp.

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

Частая ошибка

Свой заголовок подключили в угловых скобках:

C++
#include <iostream>
#include <triple.h>  // ✗

int main() {
    std::cout << triple(14) << '\n';
}
TEXT
error: 'triple.h' file not found with <angled> include; use "quotes" instead

Это ошибка компиляции. В угловых скобках компилятор ищет заголовок среди каталогов библиотек, а папку, где лежит main.cpp, не просматривает. С кавычками поиск начинается с папки самого файла.