2012-10-17 13 views
11

Per favore dimmi cosa succede se includo iostream o qualsiasi altro file di intestazione due volte nel mio file. So che il compilatore non genera errori. Il codice verrà aggiunto due volte o cosa succede internamente? Cosa succede realmente quando includiamo un file di intestazione?incluso un file di intestazione due volte in C++

+1

Grande aiuto :: http://www.cplusplus.com/forum/articles/10627/ – Abhineet

risposta

10

Include guard impedisce che il contenuto del file venga effettivamente visualizzato due volte dal compilatore.

include guard è fondamentalmente una serie di direttive condizionali di preprocessore all'inizio e alla fine di un file di intestazione:

#ifndef SOME_STRING_H 
#define SOME_STRING_H 

//... 

#endif 

Ora, se si include il file due volte poi la prima volta turno macro SOME_STRING_H non è definito e quindi il il contenuto del file viene elaborato e visualizzato dal compilatore. Tuttavia, poiché la prima cosa dopo #ifdef è #define, viene definito SOME_STRING_H e la volta successiva il contenuto del file di intestazione non viene visualizzato dal compilatore.

Per evitare conflitti, il nome della macro utilizzata nella protezione include dipende dal nome del file di intestazione.

+0

Solo una nota: quando si utilizzano gli strumenti Microsoft, si vedrà spesso un '#pragma una volta', che ha la stessa funzionalità come '#ifndef ...'. Per una migliore compatibilità con il compilatore dovresti usare quest'ultimo. – AquilaRapax

+0

Nota anche che la maggior parte dei compilatori riconoscerà questo pattern e non aprirà nemmeno il file quando lo vedrà una seconda volta. –

+0

Questo in realtà non risponde alla domanda. Sono interessato alla domanda originale perché sto guardando il codice di qualcun altro. – Frederick

2

Semplicemente ottiene saltati, a causa di codice preprocessore secondo le seguenti linee:

#ifndef MY_HEADER_H 
#define MY_HEADER_H 

<actual header code here> 

#endif 

Quindi, se si include due volte, poi MY_HEADER_H è già stato definito e tutto tra il #ifndef e #endif viene saltato dal preprocessore.

3

I file di intestazione sono bestie semplici. Quando si esegue #include <header>, tutto ciò che accade è che i contenuti di header vengono copiati nel file. Per fermare le intestazioni di essere inclusi più volte, include guards vengono utilizzati, che è il motivo per cui nella maggior parte dei file di intestazione vedrete qualcosa di simile a

#ifndef SOME_HEADER_FILE_GUARD 
#define SOME_HEADER_FILE_GUARD 

//Contents of Header 

#endif 
0

Dipende. Ad eccezione dello <assert>, lo standard richiede che lo includa (di seguito) un'intestazione standard come no-op. Questa è una caratteristica dell'intestazione, tuttavia; il compilatore (almeno concettualmente) legge e include tutto il testo dell'intestazione ogni volta che lo incontra l'inclusione.

La pratica standard per evitare più definizioni in questi casi è utilizzare includere guardie: tutto il codice C++ nell'intestazione saranno racchiusi in qualcosa come:

#ifndef SPECIAL_NAME 
#define SPECIAL_NAME 
// All of the C++ code here 
#endif SPECIAL_NAME 

Ovviamente, ciascuna intestazione bisogno di un nome diverso All'interno di un'applicazione, , in genere è possibile stabilire convenzioni basate sul nome file e sulla posizione ; qualcosa come subsystem_filename, con caratteri non legali in un simbolo C++ (se li stai usando nei tuoi nomi di file ) mappati (e molto spesso tutto in maiuscolo). Per le librerie , la procedura consigliata sarebbe quella di generare una sequenza casuale di caratteri ragionevolmente lunga ; molto più frequente (sebbene certamente inferiore da un punto di vista della qualità di implementazione) è quello di garantire che ogni simbolo inizi con un prefisso documentato.

Una libreria di sistema può, ovviamente, utilizzare simboli riservati (ad es.un simbolo che inizia con un trattino basso seguito da una lettera maiuscola) qui, per garantire che non ci sia conflitto. O può usare del tutto diverso, tecnica dipendente dall'implementazione. Microsoft, ad esempio, utilizza un'estensione del compilatore #pragma once; Gli usi di g ++ includono le guardie che iniziano sempre con _GLIBCXX (che non è un simbolo legale nel codice utente). Queste opzioni non sono necessariamente disponibili.

Problemi correlati