2011-02-08 8 views
5

Ho cercato la paura SDK per il mio progetto universitario, ma hanno notato un certo codice in questo modo:Perché includere un'intestazione e inoltrare dichiarare la classe contenuta nello stesso file cpp?

foo.h

class Foo 
{ 
    public: 
     int iSomething; 
}; 

Bar.cpp:

#include "Foo.h" 

// Forward declarations 
class Foo; 

Is c'è qualche ragione particolare per inoltrare la dichiarazione E includere l'intestazione appropriata nello stesso file cpp? Oppure la dichiarazione anticipata è ridondante perché l'intestazione viene inclusa?

EDIT:

Ogni volta che ho visto nel codice, l'istruzione include sempre prima della dichiarazione in avanti.

risposta

6

È più che semplicemente ridondante, è potenzialmente problematico. Say Foo.h cambia così Foo diventa un typedef ad una particolare istanziazione di un equivalente generico, templato - il tipo di cosa che può essere anticipata come parte della normale evoluzione del software. Poi di Bar.cpp "classe X" inutilmente causare un errore di compilazione ala:

--- fwd.h --- 
template <typename T> 
class XT 
{ 
    public: 
    int n_; 
}; 

typedef XT<int> X; 

--- fwd.cc --- 
#include "fwd.h" 

class X; 

int main() 
{ 
    X x; 
    x.n_ = 0; 
    return x.n_; 
} 

--- compilation attempt --- 
~/dev .../gcc/4.1.1/exec/bin/g++ fwd.cc -o fwd 
fwd.cc:3: error: using typedef-name 'X' after 'class' 
fwd.h:8: error: 'X' has a previous declaration here 

Questa è una ragione mi raccomando di usare sempre dedicato intestazioni forward-dichiarazione ala <iosfwd>, mantenuto con e incluso dal collettore principale per garantire la costante consistenza. Non ho mai messo "classe X"; in un file di implementazione a meno che la classe non sia definita anche lì. Ricorda che i benefici apparenti di "classe X"; le dichiarazioni anticipate non sono tanto da evitare un #include, e più che i file che includono possono essere grandi e a loro volta includere molti altri file: le intestazioni di forward forward dedicate tipicamente evitano comunque la stragrande maggioranza.

1

La dichiarazione di inoltro è ridondante, ma anche abbastanza innocua. Forse l'autore utilizza molte dichiarazioni anticipate e non garantisce rigorosamente che siano sempre richieste.

3

Se la dichiarazione di inoltro precede gli include, potrebbe eliminare una dipendenza. Provenire dal file .h attuale che lo definisce non fa nulla.

+0

Puoi elaborare? Originariamente ho scritto esattamente questa stessa cosa, ma poi ci ho pensato un po 'di più e ho pensato che se la barra in avanti-dichiara Foo, allora #include immediatamente Foo.h, dovrebbe a) produrre sempre la dichiarazione di Foo, e b) mai dipendere da un'altra intestazione che ha già dichiarato Foo. Puoi dare un esempio in cui la dichiarazione anticipata prima del #include aiuta effettivamente? – mgiuca

+0

@mgiuca - riduce i tempi di compilazione. spesso il codice usa solo puntatori e non richiede mai la dimensione effettiva della classe [e non crea mai istanze].In tali circostanze, è sufficiente una dichiarazione anticipata, risparmiando il tempo di # includere altri file. –

+0

@Foo Bah Sì, questa è una buona ragione per utilizzare una dichiarazione di inoltro * invece di * un #include. Ma non spiega perché avresti entrambi. Se si dispone di entrambi, è necessario elaborare il file incluso, indipendentemente dal fatto che sia stato utilizzato o meno. – mgiuca

2

L'originale class Foo; potrebbe essere stato rudimentale.

Ricorda che, se la sorgente utilizza solo puntatori alla classe Foo [e in realtà non tenta di creare oggetti Foo o dereferimenti Puntatori Foo], non devi definire la classe prima di usarla.

Senza vedere il codice, mi piacerebbe azzardare l'ipotesi che la versione originale del bar.cpp aveva il codice che non richiedono la definizione di foo

che uso in avanti dichiarazioni in grandi progetti per ridurre il tempo di compilazione. compilare il tempo non è un problema quando ci vuole un secondo, ma quando i progetti impiegano un'ora per costruire ogni secondo aiuta :)