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.
Przeczytałem to tutaj. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html .
Oznacza to, że jeśli klasa (klasa A) w pliku nagłówkowym nie musi używać rzeczywistej definicji niektórych klas (klasa B). W tym momencie możemy użyć deklaracji forward zamiast dołączania konkretnego pliku nagłówkowego (klasy B).
Pytanie: Jeśli klasa (klasa A) w nagłówku nie używa rzeczywistej definicji konkretnej klasy (klasa B), to w jaki sposób deklaracja przesyłania dalej pomaga skrócić czas kompilacji?
źródło
vehicle.h
,bus.h
,toybus.h
.vehicle.h
dołącz przezbus.h
ibus.h
dołącz przeztoybus.h
. więc jeśli coś zmieniębus.h
. czy kompilator otwiera się i parsujevehicle.h
ponownie? czy to kompiluje to ponownie?#pragma once
lub#ifndef __VEHICLE_H_
wpisujesz deklaracje w plikach nagłówkowych, aby zapobiec dołączaniu takich plików wiele razy (lub wielokrotnemu użyciu, przynajmniej w przypadku ifndef).ponieważ wtedy A.hpp nie musi #include B.hpp
tak staje się A.hpp
więc kiedy A.hpp jest dołączony, B.hpp nie jest domyślnie dołączony, a wszystkie pliki, które zależą tylko od A.hpp, nie muszą być rekompilowane za każdym razem, gdy b.hpp zmienia się
źródło
Pamiętaj, że preprocesor C / C ++ to osobny, czysto tekstowy etap przetwarzania. Do
#include
dyrektywa ściąga treści zawarte nagłówku i kompilator musi ją przeanalizować. Co więcej, kompilacja każdego z nich.cpp
jest całkowicie osobna, więc fakt, że kompilator właśnie przeanalizowałB.h
podczas kompilacjiB.cpp
, nie pomaga, gdy jest potrzebny ponownie podczas kompilacjiA.cpp
. I znowu podczas kompilacjiC.cpp
. ID.cpp
… I tak dalej. I każdy z tych plików musi zostać ponownie skompilowany, jeśli jakikolwiek plik w nim się zmienił.Powiedzmy, że klasa
A
używa klasyB
i klasC
iD
używa klasyA
, ale nie trzeba manipulowaćB
. Jeśli klasaA
może być zadeklarowana za pomocą tylko deklaracji forwardB
, niżB.h
jest kompilowana dwukrotnie: podczas kompilacjiB.cpp
iA.cpp
(ponieważB
nadal jest potrzebna w ramachA
metod).Ale kiedy
A.h
obejmujeB.h
, to jest kompilowany cztery razy, podczas kompilacjiB.cpp
,A.cpp
,C.cpp
iD.cpp
jak później dwa teraz pośrednio obejmujeB.h
też.Również, gdy nagłówek jest dołączany więcej niż jeden raz, preprocesor nadal musi go czytać za każdym razem. Pominie przetwarzanie zawartości ze względu na ochronę
#ifdef
, ale nadal ją odczytuje i musi szukać końca osłony, co oznacza, że musi przeanalizować wszystkie zawarte w niej dyrektywy preprocesora.(Jak wspomniano w drugiej odpowiedzi, prekompilowane nagłówki próbują obejść ten problem, ale są one własną puszką robaków; w zasadzie można je rozsądnie wykorzystać do nagłówków systemowych i tylko wtedy, gdy nie używa się ich zbyt wielu, ale nie do nagłówki w twoim projekcie)
źródło
Deklaracja przesyłania dalej jest znacznie szybciej analizowana niż cały plik nagłówka, który sam może zawierać jeszcze więcej plików nagłówka.
Ponadto, jeśli zmienisz coś w pliku nagłówkowym dla klasy B, wszystko łącznie z tym nagłówkiem będzie musiało zostać ponownie skompilowane. W przypadku deklaracji przesyłania może to być tylko plik źródłowy, w którym rezyduje implementacja A. Ale jeśli nagłówek A faktycznie zawiera nagłówek B, wszystko łącznie z tym
a.hpp
zostanie ponownie skompilowane, nawet jeśli nie używa niczego z B.źródło