Ответ
В C++ для защиты заголовочного файла от множественного включения и связанных с этим ошибок переопределения используются два основных метода.
1. Include Guards (Стражи включения) Стандартный, переносимый способ, который работает везде.
// File: my_class.h
#ifndef MY_CLASS_H // Если макрос не определен...
#define MY_CLASS_H // ... определяем его.
class MyClass {
// ... объявление класса ...
};
#endif // MY_CLASS_H
Правила для имени макроса: Оно должно быть уникальным в рамках проекта. Обычно используют имя файла в верхнем регистре с подчеркиваниями (например, PROJECT_PATH_MY_CLASS_H).
2. Директива #pragma once
Нестандартная, но широко поддерживаемая всеми основными компиляторами (GCC, Clang, MSVC) директива.
// File: my_class.h
#pragma once
class MyClass {
// ... объявление класса ...
};
| Сравнение: | Критерий | #pragma once |
Include Guards |
|---|---|---|---|
| Стандарт | Не входит, расширение компилятора | Стандартный C/C++ | |
| Скорость компиляции | Может быть быстрее (компилятор отслеживает файлы) | Медленнее (препроцессор проверяет макросы) | |
| Надежность | Может не сработать при симлинках или копиях файла | Абсолютно надежна, если имя макроса уникально | |
| Удобство | Кратко, не требует придумывания имени | Требует уникального имени и трех строк кода |
Моя практика: В современных кроссплатформенных проектах на C++ я использую #pragma once из-за удобства и скорости. Однако для библиотек, требующих максимальной переносимости, или в корпоративных стандартах, запрещающих нестандартные расширения, следует использовать Include Guards.