Помните, препроцессор C / C ++ - это отдельный, чисто текстовый этап обработки. В #includeдирективе вытягивает содержание включенного заголовка и компилятор должен разобрать его. Более того, компиляция каждого из них .cppявляется совершенно отдельной, поэтому тот факт, что компилятор просто анализирует B.hпри компиляции B.cpp, не помогает ему в меньшей степени, когда он снова нужен при компиляции A.cpp. И снова при компиляции C.cpp. И D.cpp. И так далее. И каждый из этих файлов должен быть перекомпилирован, если какой-либо включенный в него файл изменился.
Так, скажем, класс Aиспользует класс Bи классы Cи Dиспользует класс A, но не нуждается в манипулировании B. Если класс Aможет быть объявлен просто с помощью forward-декларации of B, то B.hон компилируется дважды: при компиляции B.cppи A.cpp(потому что Bвсе еще требуется внутри Aметодов).
Но когда A.hвключает в себя B.h, он компилируется в четыре раза, при компиляции B.cpp, A.cpp, C.cppи , D.cppкак позже два ныне косвенно включает в себя B.hтакже.
Также, когда заголовок включен более одного раза, препроцессор все равно должен читать его каждый раз. Он пропустит обработку своего содержимого из-за защиты #ifdefs, но он все еще читает ее и должен искать конец защиты, что означает, что он должен проанализировать все директивы препроцессора внутри.
(Как упоминалось в другом ответе, предварительно скомпилированные заголовки являются попыткой обойти эту проблему, но они представляют собой собственную червь; в основном вы можете разумно использовать их для системных заголовков и только если вы не используете их слишком много, но не для заголовки в вашем проекте)
vehicle.h,bus.h,toybus.h.vehicle.hвключатьbus.hиbus.hвключатьtoybus.h. так что если я сделаю некоторые изменения вbus.h. компилятор открывает иvehicle.hснова разбирает ? это компилирует это снова?