Помните, препроцессор 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
также.
Также, когда заголовок включен более одного раза, препроцессор все равно должен читать его каждый раз. Он пропустит обработку своего содержимого из-за защиты #ifdef
s, но он все еще читает ее и должен искать конец защиты, что означает, что он должен проанализировать все директивы препроцессора внутри.
(Как упоминалось в другом ответе, предварительно скомпилированные заголовки являются попыткой обойти эту проблему, но они представляют собой собственную червь; в основном вы можете разумно использовать их для системных заголовков и только если вы не используете их слишком много, но не для заголовки в вашем проекте)
vehicle.h
,bus.h
,toybus.h
.vehicle.h
включатьbus.h
иbus.h
включатьtoybus.h
. так что если я сделаю некоторые изменения вbus.h
. компилятор открывает иvehicle.h
снова разбирает ? это компилирует это снова?