2014-07-24 10 views
8

Stavo leggendo su più inclusioni della stessa intestazione in un unico file, e ho trovato una dichiarazione interessante (link):Quando è utile includere più volte la stessa intestazione in un file?

Ci sono un paio di trucchi con i file di intestazione sono stati deliberatamente includerlo più volte (questo in realtà fornisce una utile funzione ).

Capisco che questi trucchi sono probabilmente indesiderate e confusa in progetti reali (soprattutto perché le persone prendono precauzioni contro più inclusioni, come include guards e #pragma once). Ma ancora, quali sono questi trucchi? Ho trovato alcune idee, ma vorrei vedere alcuni esempi reali (idealmente, sicuri e provati).

I miei pensieri:

  • Gli pseudo-modelli in C, dove i parametri del modello sono sostituite con le definizioni del preprocessore. Può essere fatto senza inclusioni, ma le funzioni possono essere troppo grandi o troppo numerose, quindi fare un file separato avrebbe senso.
  • Costruzione struttura/classe blocco a blocco (concatenazione di pezzi). Può aiutare a emulare l'ereditarietà in C e prevenire la duplicazione del codice quando si definiscono le strutture con membri comuni.
  • Tabelle di ricerca e altre strutture di dati in fase di compilazione (sempre con l'ausilio delle definizioni del preprocessore).
+3

Macro X. –

+0

Forse se stai usando '# define' e' # undef' cosparso in un file sorgente ... –

+0

Perché non chiedi alla persona che l'ha postata? – juanchopanza

risposta

7

#include "file" significa prendere il file di intestazione e mettere tutto il suo contenuto al posto della linea #include.

Abbiamo solito intestazioni usati per le definizioni tipo e per l'aggiunta di dichiarazioni l'ora di un file di origine. definire lo stesso tipo due volte in un file (un inclusivo circolare lo causerà sempre) fornisce un errore di compilazione, quindi usiamo #ifndef o #pragma once. (o entrambi)

Ma possiamo anche inserire un codice ripetuto e macro e includerlo più volte, anche nello stesso file. in tal caso, non useremo #ifndef#pragma once. Se lo fai, devi fare molta attenzione e fallo solo se sai cosa stai facendo.

Ad esempio: se in alcuni OS chiamare una funzione specifica del sistema (o anche macro ac come: offsetof) causare un sacco di avvertimenti, e ti dà fastidio, e che il codice è buona, ma si don 'Voglio disabilitare tutti gli avvisi che hai su tutto il progetto o il file, devi solo disabilitarlo quando chiami la funzione specifica.

//suppress the warnings: 
#if defined(__GNUC__) 
    #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 
    #pragma GCC diagnostic push 
    #pragma GCC diagnostic ignored "-Wreorder" 
    #pragma GCC diagnostic ignored "-Wunused-function" 
    #pragma GCC diagnostic ignored "-Wunused-variable" 
    #pragma GCC diagnostic ignored "-Wsign-compare" 
    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 
    #pragma GCC diagnostic ignored "-Wsequence-point" 
    #endif 
#endif // __GNUC__ 

//here you call the function... 
func(x,y,z); 

//unsupress: bring back the warnings to normal state 
#if defined(__GNUC__) 
    #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 
    #pragma GCC diagnostic pop 
    #endif 
#endif // __GNUC__ 

Questo renderà il vostro codice a guardare molto sporca, soprattutto se si chiama la funzione più volte.

Una possibile soluzione, (non sto suggerendo che sia la migliore ...) consiste nel creare 2 intestazioni, in una per sopprimere le avvertenze e nell'altra per annullare la soppressione.

In tal caso, il codice può assomigliare a questo:

#include "suppress.h" 
func(x,y,z); 
#include "unsuppress.h" 

//.... more code come here 
//now when call it again: 
#include "suppress.h" 
func(x,y,z); 
#include "unsuppress.h" 
1

L'esempio 'standard' è l'intestazione <assert.h>. L'effetto di includere dipende dal valore della NDEBUG:

#include <assert.h> 

void func1(void) 
{ 
    assert(...); 
} 

#undef NDEBUG 
#include <assert.h> 

void func2(void) 
{ 
    assert(...); 
} 

#define NDEBUG 
#include <assert.h> 

void func3(void) 
{ 
    assert(...); 
} 

L'affermazione in func1() è attivo a meno che qualcosa nell'ambiente di compilazione ha fissato NDEBUG nel momento in cui è stato incluso <assert.h>. L'asserzione in func2() è attiva perché NDEBUG non è stato definito quando è stato incluso <assert.h>. L'asserzione in func3() è inattiva perché NDEBUG è stata definita quando è stato incluso <assert.h>.

Detto questo, non ho mai usato questa funzione nella vita reale, ma lo standard C benedice (impone) il comportamento mostrato.

Si noti che ciò non avviene per caso; succede perché l'intestazione è volutamente progettata per essere (ri) utilizzata più volte in una singola TU.

Problemi correlati