Reduce the number of #include files in header files. It will reduce build times. Instead, put include files in source code files and use forward declarations in header files.
Я прочитал это здесь. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html .
Таким образом, он говорит, что если класс (класс A) в заголовочном файле не должен использовать фактическое определение некоторого класса (класс B). В то время мы можем использовать предварительное объявление вместо включения конкретного (класса B) заголовочного файла.
Вопрос: Если класс (класс A) в заголовке не использует фактическое определение определенного класса (класс B), то как предварительное объявление помогает сократить время компиляции?
источник
vehicle.h
,bus.h
,toybus.h
.vehicle.h
включатьbus.h
иbus.h
включатьtoybus.h
. так что если я сделаю некоторые изменения вbus.h
. компилятор открывает иvehicle.h
снова разбирает ? это компилирует это снова?#pragma once
или#ifndef __VEHICLE_H_
вводите объявления в заголовочных файлах, чтобы такие файлы не включались многократно (или использовались многократно, по крайней мере, в случае ifndef).потому что тогда A.hpp не нужно включать
поэтому A.hpp становится
поэтому, когда A.hpp включен, B.hpp не включается неявно, и все файлы, которые зависят только от A.hpp, не нужно перекомпилировать каждый раз, когда изменяется b.hpp.
источник
Помните, препроцессор C / C ++ - это отдельный, чисто текстовый этап обработки. В
#include
директиве вытягивает содержание включенного заголовка и компилятор должен разобрать его. Более того, компиляция каждого из них.cpp
является совершенно отдельной, поэтому тот факт, что компилятор просто анализируетB.h
при компиляцииB.cpp
, не помогает ему в меньшей степени, когда он снова нужен при компиляцииA.cpp
. И снова при компиляцииC.cpp
. ИD.cpp
. И так далее. И каждый из этих файлов должен быть перекомпилирован, если какой-либо включенный в него файл изменился.Так, скажем, класс
A
использует классB
и классыC
иD
использует классA
, но не нуждается в манипулированииB
. Если классA
может быть объявлен просто с помощью forward-декларации ofB
, тоB.h
он компилируется дважды: при компиляцииB.cpp
иA.cpp
(потому чтоB
все еще требуется внутриA
методов).Но когда
A.h
включает в себяB.h
, он компилируется в четыре раза, при компиляцииB.cpp
,A.cpp
,C.cpp
и ,D.cpp
как позже два ныне косвенно включает в себяB.h
также.Также, когда заголовок включен более одного раза, препроцессор все равно должен читать его каждый раз. Он пропустит обработку своего содержимого из-за защиты
#ifdef
s, но он все еще читает ее и должен искать конец защиты, что означает, что он должен проанализировать все директивы препроцессора внутри.(Как упоминалось в другом ответе, предварительно скомпилированные заголовки являются попыткой обойти эту проблему, но они представляют собой собственную червь; в основном вы можете разумно использовать их для системных заголовков и только если вы не используете их слишком много, но не для заголовки в вашем проекте)
источник
Форвардное объявление намного быстрее разбирается, чем целый заголовочный файл, который сам может содержать еще больше заголовочных файлов.
Кроме того, если вы измените что-либо в файле заголовка для класса B, все, что включает этот заголовок, придется перекомпилировать. С предварительным объявлением, это может быть только исходный файл, в котором находится реализация A. Но если заголовок A фактически включает заголовок B, все, включая включая,
a.hpp
будет также перекомпилировано, даже если он не использует ничего из B.источник