Al giorno d'oggi, Include guard è un argomento che ha catturato l'attenzione di molte persone in tutto il mondo. Con il suo impatto sulla società e su diversi aspetti della vita quotidiana, Include guard è diventato argomento di discussione e dibattito costante. Dalla sua influenza sull’economia al suo ruolo nella cultura popolare, Include guard è diventato rilevante in innumerevoli contesti. In questo articolo esploreremo vari aspetti di Include guard e analizzeremo il suo impatto su diversi aspetti della vita moderna. Dalla sua origine alla sua evoluzione nel tempo, Include guard continua ad essere un argomento di interesse per coloro che cercano di comprendere meglio il mondo che li circonda.
Nei linguaggi C e C++, le #include guard sono delle particolari direttive (o macro) che vengono usate nei file header per evitare problemi di doppia definizione in fase di linking.
Supponiamo di avere 3 file sorgenti senza #include guard:
class persona
{
// dichiarazione
};
#include "persona.h"
class impiegato : public persona
{
// dichiarazione
};
#include "persona.h"
#include "impiegato.h"
int main()
{
persona p;
impiegato i;
}
In fase di compilazione, verrà creato un file oggetto: main.o Gli header files vengono inclusi nel file sorgente main.cpp ovvero il loro contenuto viene copiato dal preprocessore all'inizio del file main.cpp prima della compilazione.
Senza interessarci delle implementazioni di persona e impiegato, il nostro obiettivo sarà quello di usare indistintamente una persona o un impiegato (ed i relativi metodi). Quando il linker andrà a creare l'eseguibile definitivo, avrà una doppia dichiarazione di persona e rilascerà un errore di linkaggio. Infatti la classe persona sarà definita sia nel file persona.o che nel file impiegato.o. In quest'ultimo caso, quello del file impiegato.o, è necessario inserire la dichiarazione di persona per via della direttiva #include specificata.
Per non avere questo tipo di problema basta utilizzare le #include guard in questa maniera:
#ifndef PERSONA_H
#define PERSONA_H
// tutto il resto
#endif // PERSONA_H
Con questo accorgimento, la prima volta che viene incluso persona.h, il simbolo PERSONA_H non è ancora stato definito, e di conseguenza viene creato. Le successive volte che viene incluso persona.h, il simbolo PERSONA_H è definito, perciò la parte relativa alla definizione della classe persona non viene tenuta in considerazione.
Di buona norma le #include guard devono essere inserite in tutti i file .h in modo da assicurare una maggiore trasparenza al programmatore evitando di incorrere in questo tipo di errore.
La seguente è un'alternativa equivalente agli include guard ma più breve e più semplice e a volte incrementa la velocità di compilazione.
#pragma once
//tutto il resto
Indica che il file deve essere incluso una sola volta nella compilazione.
Nonostante questa direttiva non sia definita negli standard del C/C++, è definita in quasi tutti i compilatori.
| Compiler | #pragma once |
|---|---|
| Clang | Supportato |
| Comeau C/C++ | Supportato |
| C++Builder XE3 | Supportato |
| Digital Mars C++ | Supportato |
| GCC | Supportato |
| HP C/aC++ | Supportato |
| IBM XL C/C++ | Supportato |
| Intel C++ Compiler | Supportato |
| Microsoft Visual C++ | Supportato |
| Pelles C | Supportato |
| ARM DS-5 | Supportato |
| IAR C/C++ | Supportato |
| Solaris Studio C/C++ | Non supportato |