Заголовний файл

У програмуваннізаголовний файл(англ. header file ) абопідключається файл— файл, вміст якого автоматично додається препроцесором у вихідний текст там, де розташовується деяка директива ( в Паскалі, #include у Сі).

У мовах програмування Сі і C++ заголовні файли - основний спосіб підключити до програми типи даних, структури, прототипи функцій, типи, що перерахуються, і макроси, що використовуються в іншому модулі. За промовчанням використовується розширення.h; іноді для файлів заголовків мови C++ використовують розширення.hpp.

Щоб уникнути повторного включення одного й того ж коду, використовуються директиви #ifndef, #define, #endif.

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

За традицією, що склалася, в заголовних файлах оголошують функції стандартної бібліотеки Сі і Сі ++.

В інших мовах (наприклад, Паскалі) застосовується розвинена система модулів. Але й у них заголовні файли мають певну цінність. Справа в тому, що два файли (основний та заголовковий) зливаються в одну одиницю трансляції, і тому заголовковий файл може містити директиви препроцесора, незакінчені синтаксичні конструкції.

Зміст

У сучасних мовах програмування програми складаються з модулів, що компілюються окремо. У зв'язку з цим виникає питання: як вказати, що підпрограма чи змінна Xвизначена в модулі Y? Для цього існує кілька рішень, у Сі застосовано таке.

В одній з одиниць компіляції (тобто з -файлі) описується функція, наприклад:

Щоб її можна було посилатися з інших одиниць компіляції, потрібно оголосити її з допомогою прототипу функції, тобто:

Списки ініціалізованих констант у заголовному файлі вибираються препроцесором для заміни їх значенням цих констант у файлі. Функції заголовного файлу, що включаються, обрамляються директивами макрозахисту препроцесора для уникнення їх дублювання в файлі, що включає (виникнення такої ситуації можливе при класовому або файловому успадкування):

Крім конструкції #ifndef - #endif іноді застосовується нестандартна #pragma once:

Альтернатива заголовним файлам - отримання інформації про оголошені типи, функції і т. д. безпосередньо з відкомпілюваного модуля. Так роблять мови Паскаль, Java та інші.

Переваги

Перевага заголовних файлів в першу чергу у спрощенні компілятора: без заголовних файлів компілятор і компонувальник виконують ту саму роботу, перевіряючи, чи є в модулі Y відкомпільована функція X .

Якщо модуль правильно написаний, за допомогою умовної компіляції можна вимкнути частину його функціональності. Наприклад, в даному випадку ми відмовляємося від компонування до програми величезної бібліотеки STL:

У випадку, якщо модуль поширюється вже відкомпільованим (бібліотека), файл заголовки буде одночасно документацією по користуванню модулем.

Якщо програміст виправив реалізацію функції в c-файлі, не зачепивши заголовка, це не викличе каскадної перекомпіляції всіх модулів, які використовують цей заголовок.

Заголовковий файл дозволяє задати те, що неможливовстановити за допомогою модулів — підстановки за допомогою #define, директиви компілятора, незакінчені синтаксичні конструкції…

Спрощується взаємодія між модулями, написаними різними мовами. Компілятору і компоновщику взагалі байдуже, написаний модуль, що викликається тією ж мовою або іншою. До того ж, різні мови можуть скомпілювати свої модулі в однакові об'єктні файли — у такому випадку виходить один компонувальник на кілька мов. Так само просто зробити бібліотеку, яка на вибір користувача включається в проект у вигляді CPP-файлів, зберігається заздалегідь відкомпільованою і прикомпоновується статично, або прикомпоновується як DLL.

Недоліки

Заголовні файли набагато повільніше - щоб відкомпілювати 10 c-файлів, до кожного з яких підключений довгий h-файл, компілятору доведеться пройти по заголовку 10 разів. Щоб упоратися з цією проблемою, у багатьох компіляторах використовують попередньо відкомпільовані заголовки.

Заголовні файли разом з деякими об'єктами мови C++ (константи, inline-функції, шаблони, static-змінні) утворюють великовагові конструкції.

Програміст повинен синхронно змінювати заголовки функцій у двох місцях. Якщо раптом він змінив c-файл, забувши зробити те ж саме з h-файлом, компонувальник видасть розпливчасте повідомлення про помилку без номера рядка. Особливо це помітно в C++, де та сама функція може мати різний набір аргументів, і перевірка лише на рівні компілятора не спрацьовує. Якщо програміст випадково залишить конструкцію в h-файлі незакінченою, помилка буде зовсім в іншому c-або h-файлі.

Проектам із мов сімейства Сі властиві складні схеми складання проекту. Адже (як мінімум у стандартному C++) треба включити в проект бібліотеку або у вигляді CPP-файлів, або ввідкомпілюваному вигляді. Навіть якщо (наприклад, Visual C++) для цього є директиви препроцесора, бібліотеку все одно доведеться зібрати.