La tua domanda indica che non capisci il processo di compilazione (la maggior parte si applica a c e anche a c ++).
L'unità fondamentale della compilazione è un file sorgente; per C ++ la convenzione è usare l'estensione del file .cpp. L'estensione potrebbe essere qualsiasi cosa, ma la maggior parte dei compilatori usa l'estensione per determinare come elaborare il file, es. .cpp significa c ++, .o significa oggetto, .c significa diritto c, ecc. I file sorgente sono complied in file object (nominalmente .obj o .o). I file oggetto sono collegati insieme per creare file eseguibili.
Il compilatore non sa nulla dei file header. C'è un pre-processore che sostituisce le direttive #include con il contenuto del file di intestazione ed elabora altre direttive pre-processore, l'output risultante è ciò che il compilatore vede come input; questo è il motivo per cui le intestazioni sono incluse nei file sorgente e non viceversa.
I file header non sono strettamente necessari per compilare source to object; sono uno strumento per gestire la complessità, organizzare e modulare i file sorgente. Come hanno spiegato le altre risposte, quando foo.cpp deve fare riferimento a qualcosa in bar.cpp, ad esempio baz (), foo.cpp deve avere alcune informazioni descrittive su baz () in modo che possa generare un riferimento che il linker può risolvere.
Si potrebbe semplicemente inserire queste informazioni in foo.cpp, ma ciò duplicherebbe le informazioni in bar.cpp. La soluzione a questa duplicazione consiste nel mettere tutte le informazioni descrittive in un altro file, che chiamiamo un file di intestazione (nominalmente .h o .hpp.) Con bar.h le informazioni che devono essere incluse in foo.cpp e bar.cpp è solo in un file, che viene inserito nel file quando il pre-processore trova la direttiva #include. Ciò diventa inestimabile con l'aumentare della complessità del progetto.
Gran parte del processo di compilazione è nascosto dietro un IDE o un makefile. Compilare un piccolo progetto a mano sarà molto istruttivo per imparare come funziona il processo di compilazione. La prima volta che ho dovuto scrivere a .makefile da zero a scuola tutto il mistero del processo di compilazione è svanito; Ho dovuto imparare tutti i dettagli per svolgere il compito.
La compilazione e il collegamento del tuo esempio sarebbero 3 operazioni, in due fasi:
- Compila i file sorgente:
- Compilare foo.cpp in foo.o (ad esempio gcc -c -o foo.o foo.cpp)
- Compila bar.cpp in bar.o (ad esempio gcc -c -o bar.o bar.cpp)
- Collega i file oggetto:
- link foo.o e bar.o in programma (ad esempio gcc -o programma foo.o bar.o)
Durante la fase di compilazione ogni file viene elaborato individualmente. I file oggetto risultanti contengono codice macchina e riferimenti esterni (cose non presenti nel file sorgente, ma in qualche altro file sorgente).
Il passo finale è quello di collegare gli oggetti, questo è quando i riferimenti sono risolti, se si dimentica di includere il file oggetto nel comando link, fallirà con riferimenti esterni non risolti; questo è il passo in cui sono necessarie tutte le informazioni. I moderni compilatori possono gestire tutti questi passaggi con un singolo comando, ma questo nasconde il processo.