Це один із тих типів стандартів кодування "повинен", а не "повинен". Причина полягає в тому, що вам досить доведеться написати аналізатор C ++ для його виконання.
Дуже поширеним правилом для файлів заголовків є те, що вони повинні стояти самостійно. Файл заголовка не повинен вимагати, щоб деякі інші заголовні файли були #included, перш ніж включати заголовки. Це вимога, яку можна перевірити. З огляду на кілька випадкових заголовків foo.hh
, слід скомпілювати та запустити наступне:
#include "foo.hh"
int main () {
return 0;
}
Це правило має наслідки щодо використання інших класів у деяких заголовках. Іноді цих наслідків можна уникнути, якщо вперед оголосити ці інші класи. Це неможливо з великою кількістю стандартних бібліотечних класів. Немає способу переслати оголошення про шаблони, такі як std::string
або std::vector<SomeType>
. Ви повинні мати #include
ці заголовки STL у заголовку, навіть якщо єдиним використанням цього типу є аргумент функції.
Ще одна проблема полягає в речах, які ви випадково перетягуєте. Приклад: врахуйте наступне:
файл foo.cc:
#include "foo.hh"
#include "bar.hh"
void Foo::Foo () : bar() { /* body elided */ }
void Foo::do_something (int item) {
...
bar.add_item (item);
...
}
Тут bar
представлений Foo
тип даних класу Bar
. Ви зробили правильно тут і включили #included bar.hh, хоча це повинно було бути включено до заголовка, що визначає клас Foo
. Однак ви не включили речі, якими користуються Bar::Bar()
та Bar::add_item(int)
. Є багато випадків, коли ці дзвінки можуть призвести до додаткових зовнішніх посилань.
Якщо ви проаналізуєте foo.o
за допомогою такого інструменту nm
, виявиться, що функції в foo.cc
викликають всі види матеріалів, для яких ви не зробили відповідного #include
. Тож чи варто додати #include
директиви для цих випадкових зовнішніх посилань foo.cc
? Відповідь абсолютно ні. Проблема полягає в тому, що дуже важко відрізнити ті функції, які викликаються випадково, від тих, які викликаються безпосередньо.