Tu banner alternativo

Include guard

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.

Tu banner alternativo

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.

Esempio

Supponiamo di avere 3 file sorgenti senza #include guard:

persona.h

class persona
{
    // dichiarazione
};

impiegato.h

#include "persona.h"

class impiegato : public persona
{
    // dichiarazione
};

main.cpp

#include "persona.h"
#include "impiegato.h"

int main()
{
    persona p;
    impiegato i;
}

Compilazione

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:

persona.h

#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.

#pragma once

La seguente è un'alternativa equivalente agli include guard ma più breve e più semplice e a volte incrementa la velocità di compilazione.

persona.h

#pragma once

//tutto il resto

Indica che il file deve essere incluso una sola volta nella compilazione.

Portabilità

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