Пам'ятайте, що препроцесор 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
знову? чи складе це знову?