C++ Includi le guardie


Esempio

Un file di intestazione può essere incluso da altri file di intestazione. Un file sorgente (unità di compilazione) che include più intestazioni può quindi, indirettamente, includere alcune intestazioni più di una volta. Se un tale file di intestazione che è incluso più di una volta contiene definizioni, il compilatore (dopo la pre-elaborazione) rileva una violazione della regola di una definizione (ad esempio §3.2 dello standard C ++ 2003) e pertanto genera una diagnostica e la compilazione non riesce.

L'inclusione multipla è impedita usando "include guardie", che a volte sono anche conosciute come guardie di intestazione o macro guardie. Questi sono implementati usando il preprocessore #define , #ifndef , direttive #endif .

per esempio

// Foo.h
#ifndef FOO_H_INCLUDED 
#define FOO_H_INCLUDED

class Foo    //  a class definition
{
};

#endif

Il vantaggio principale dell'utilizzo di protezioni include è che funzioneranno con tutti i compilatori e i preprocessori conformi agli standard.

Tuttavia, le guardie includono anche alcuni problemi per gli sviluppatori, in quanto è necessario garantire che le macro siano uniche all'interno di tutte le intestazioni utilizzate in un progetto. Nello specifico, se due (o più) intestazioni utilizzano FOO_H_INCLUDED come guardia di inclusione, la prima di quelle intestazioni incluse in una unità di compilazione impedirà efficacemente che gli altri vengano inclusi. Particolari sfide vengono introdotte se un progetto utilizza un numero di librerie di terze parti con i file di intestazione che capita di utilizzare guardie in comune.

È inoltre necessario assicurarsi che le macro utilizzate in protezioni non siano in conflitto con altre macro definite nei file di intestazione.

La maggior parte delle implementazioni C ++ supporta anche la direttiva #pragma once che garantisce che il file venga incluso solo una volta all'interno di una singola compilation. Questa è una direttiva standard di fatto , ma non fa parte di alcuno standard ISO C ++. Per esempio:

// Foo.h
#pragma once

class Foo
{
};

Mentre #pragma once evita alcuni problemi associati alle guardie, un #pragma - per definizione negli standard - è intrinsecamente un hook specifico del compilatore, e verrà ignorato silenziosamente dai compilatori che non lo supportano. I progetti che utilizzano #pragma once sono più difficili da trasferire ai compilatori che non lo supportano.

Un certo numero di linee guida di codifica e standard di garanzia per C ++ in particolare scoraggiano qualsiasi uso del preprocessore diverso da #include file di intestazione o allo scopo di inserire protezioni incluse nelle intestazioni.