Пам'ятайте, що препроцесор C / C ++ - це окремий, чисто текстовий, етап обробки. У #includeдирективі витягує вміст включеного заголовка і компілятор повинен розібрати його. Більше того, компіляція кожного .cppє абсолютно окремою, тому той факт, що компілятор щойно розбирався B.hпід час компіляції B.cpp, не допомагає ні найменше, коли він знову потребує при компілюванні A.cpp. І знову при складанні C.cpp. ІD.cpp . І так далі. І кожен із цих файлів повинен бути перекомпільований, якщо якийсь файл, що входить до нього, змінився.
Так, скажімо, клас Aвикористовує клас Bта класи Cта Dвикористовує клас A, але не потрібно маніпулювати ними B. Якщо клас Aможна оголосити за допомогою простого прямого оголошення B, тоді B.hвін складається двічі: при компілюванні B.cppта A.cpp(тому що Bвсе ще потрібен всередині Aметодів).
Але коли A.hвключає в себе B.h, він компілюється в чотири рази, при компіляції B.cpp, A.cpp, C.cppі , D.cppяк пізніше два нині побічно включає в себе B.hтакож.
Крім того, коли заголовок включений більш ніж один раз, препроцесор до сих пір читати його кожен раз. Вона пропустить обробку вмісту через захист#ifdef , але він все ще читає його і потребує пошуку кінця захисту, а значить, він повинен проаналізувати всі директиви препроцесора всередині.
(Як вже згадувалося в іншій відповіді, попередньо складені заголовки намагаються обійти це питання, але вони є власною башкою хробаків; в основному їх можна розумно використовувати для заголовків системи, і лише якщо ви не використовуєте занадто багато їх, але не для заголовки у вашому проекті)
vehicle.h,bus.h,toybus.h.vehicle.hвключатиbus.hіbus.hвключатиtoybus.h. тож якщо я щось змінюbus.h. чи відкриє компілятор і проаналізуєvehicle.hзнову? чи складе це знову?