Одна з труднощів з автоматичним виключенням дублікатів заголовка полягає в тому, що стандарт C відносно беззвучний щодо того, що означає назви файлів. Наприклад, припустимо , що основний файл компілюється містить директиви #include "f1.h"
і #include "f2.h"
, і знайдені файли для цих директив і містять #include "f3.h"
. Якщо f1.h
і f2.h
знаходяться в різних каталогах, але вони були знайдені шляхом пошуку включають шляхи, то було б незрозуміло, що #include
директиви в межах цих файлів повинні були завантажувати один і той же f3.h
файл або різні.
Справа стає ще гіршою, якщо додати можливості включення файлів, включаючи відносні шляхи. У деяких випадках, коли файли заголовків використовують відносні шляхи для вкладених файлів, включають директиви, і де потрібно, щоб уникнути будь-яких змін у наданих файлах заголовків, можливо, буде потрібно дублювати файл заголовка в декількох місцях у структурі каталогів проекту. Незважаючи на те, що існує декілька фізичних копій цього заголовкового файлу, їх слід розцінювати семантично так, ніби вони є одним файлом.
Якщо #pragma once
директива дозволила слідувати ідентифікатору once
із семантикою, за якою компілятор повинен пропустити файл, якщо ідентифікатор збігається з попередньою #pragma once
директивою, то семантика була б однозначною; компілятор, який міг би сказати, що #include
директива завантажує той самий #pragma once
тег-файл, що і попередній, це могло б заощадити трохи часу, пропустивши файл, не відкриваючи його знову, але таке виявлення не було б семантично важливим, оскільки файл буде пропущений чи чи ні ім'я файлу було визнано збігом. Я не знаю, що жоден компілятор працює таким чином. Маючи компілятор, спостерігайте, чи файл відповідає шаблону, #ifndef someIdentifier / #define someIdentifier / #endif [for that ifndef] / nothing following
і трактує таку річ, як рівнозначну вище, #pragma once someIdentifier
якщоsomeIdentifier
залишається визначеним, по суті так само добре.
#pragma once
який повідомляє компілятору включити цей файл лише один раз.