Dichiarazione in avanti vs include


17

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.

Ho letto questo qui. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html .

Quindi dice se una classe (classe A) nel file di intestazione non ha bisogno di usare la definizione effettiva di una classe (classe B). In quel momento possiamo usare la dichiarazione diretta invece di includere il particolare file di intestazione (classe B).

Domanda: se la classe (classe A) nell'intestazione se non utilizza la definizione effettiva di una particolare classe (classe B), come può la dichiarazione forward aiutare a ridurre i tempi di compilazione?

Risposte:


11

Al compilatore non importa se la classe A utilizza la classe B. Sa solo che quando viene compilata la classe A e non ha una precedente dichiarazione di classe B (dichiarazione in avanti o altro), va nel panico e la contrassegna come un errore.

Ciò che è importante qui è che il compilatore sa che non hai provato a compilare un programma dopo che il tuo gatto ha camminato sulla tastiera e creato alcune lettere casuali che possono o meno essere interpretate come una classe.

Quando vede un'inclusione, per poter usare qualsiasi informazione contenuta all'interno, deve aprire il file e analizzarlo (indipendentemente dal fatto che sia effettivamente necessario o meno). Se quel file include quindi altri file, anche quelli devono essere aperti e analizzati, ecc. Se ciò può essere evitato, è generalmente una buona idea usare invece una dichiarazione diretta.

Modifica : l'eccezione a questa regola sono le intestazioni precompilate. In questo caso, tutte le intestazioni vengono compilate e salvate per compilazioni future. Se le intestazioni non cambiano, il compilatore può usare in modo intelligente le intestazioni precompilate delle compilazioni precedenti e quindi ridurre i tempi di compilazione, ma funziona bene solo se non è necessario cambiare le intestazioni.


Grazie per la spiegazione. Poi ok come ad esempio pensate che ci sono tre file di intestazione vehicle.h, bus.h, toybus.h. vehicle.hincludere da bus.he bus.hincludere da toybus.h. quindi se faccio qualche cambiamento in bus.h. il compilatore si apre e analizza di vehicle.hnuovo? lo compila di nuovo?
Nayana Adassuriya,

1
@NayanaAdassuriya Sì, viene incluso e analizzato ogni volta, motivo per cui vedi #pragma onceo #ifndef __VEHICLE_H_digiti dichiarazioni nei file di intestazione per impedire che tali file vengano inclusi più volte (o vengano utilizzati più volte almeno nel caso di ifndef).
Neil,

4

perché allora A.hpp non ha bisogno di #includere B.hpp

così diventa A.hpp

class B;//or however forward decl works for classes

class A
{
    B* bInstance_;
//...
}

quindi quando A.hpp è incluso allora B.hpp non è incluso implicitamente e tutti i file che dipendono solo da A.hpp non devono essere ricompilati ogni volta che b.hpp cambia


ma nel file sorgente (A.cpp). è necessario includere il file di intestazione effettivo (Bh). Quindi ogni volta che deve compilare. Alla fine in entrambi i casi Bh deve ricompilarsi con le modifiche. Qualcosa di diverso?
Nayana Adassuriya,

@NayanaAdassuriya no perché A usa solo un puntatore a B e le modifiche a B non influiranno su A.hpp (o sui file che lo includono)
maniaco del cricchetto

@NayanaAdassuriya: Sì, A.cpp dovrà ricompilare (se usa la definizione di B all'interno dei metodi di A, ma di solito lo fa), ma C.cpp, che usa A, ma non B direttamente, non lo farà.
Jan Hudec,

3

Ricorda, il preprocessore C / C ++ è una fase di elaborazione separata, puramente testuale. La #includedirettiva estrae il contenuto dell'intestazione inclusa e il compilatore deve analizzarlo. Inoltre, la compilazione di ciascuno .cppè completamente separata, quindi il fatto che il compilatore abbia appena analizzato B.hdurante la compilazione B.cppnon lo aiuta minimamente quando ne ha bisogno di nuovo durante la compilazione A.cpp. E ancora durante la compilazione C.cpp. E D.cpp. E così via. E ciascuno di quei file deve essere ricompilato se uno qualsiasi dei file inclusi è cambiato.

Quindi diciamo che la classe Ausa la classe Be le classi Ce Dusa la classe A, ma non è necessario manipolarla B. Se la classe Apuò essere dichiarata solo con la dichiarazione forward di B, allora B.hviene compilato due volte: durante la compilazione B.cppe A.cpp(perché Bè ancora necessario all'interno Adei metodi).

Ma quando A.hcomprende B.h, viene compilato quattro volte-durante la compilazione B.cpp, A.cpp, C.cppe D.cppcome più tardi due ora indirettamente includono B.hanche.

Anche quando l'intestazione è inclusa più di una volta, il preprocessore deve ancora leggerlo ogni volta. Salterà l'elaborazione del suo contenuto a causa delle protezioni #ifdef, ma lo legge ancora e deve cercare l'estremità della protezione, il che significa che deve analizzare tutte le direttive del preprocessore all'interno.

(Come menzionato nell'altra risposta, le intestazioni precompilate tentano di aggirare questo problema, ma sono la loro lattina di worm; in pratica puoi ragionevolmente usarle per le intestazioni di sistema e solo se non ne stai usando troppe intestazioni nel tuo progetto)


+1, l'intestazione-include diventa solo un problema serio quando hai un numero abbastanza grande di classi, non quando hai solo due classi A e B. Tutti gli altri post sembrano mancare quel punto centrale.
Doc Brown,

2

Un'analisi diretta è molto più veloce da analizzare rispetto a un intero file di intestazione che può includere anche più file di intestazione.

Inoltre, se si modifica qualcosa nel file di intestazione per la classe B, tutto ciò che include quell'intestazione dovrà essere ricompilato. Con una dichiarazione in avanti, questo potrebbe essere solo il file di origine in cui risiede l'implementazione di A. Ma se l'intestazione di A in realtà includeva l'intestazione di B, anche tutto ciò che a.hppverrà verrà ricompilato, anche se non usa nulla di B.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.