2009-10-29 5 views
6

Alcune classi, ad esempio le eccezioni o i modelli, richiedono solo il file di intestazione (.h), spesso non è associato a .cpp.È buona norma creare sempre un file .cpp per ogni .h in un progetto C++?

Ho visto alcuni progetti erano (per alcune classi) non ci sono file .cpp associati ai file di intestazioni, forse perché l'implementazione è talmente breve che viene eseguita direttamente in .h, o forse per altri motivi, come le classi template, in cui è obbligatorio includere l'implementazione nell'intestazione.

Qual è la tua opinione, se una classe è troppo corta, dovrei evitare di creare un file .cpp e scrivere il codice direttamente nel file di intestazione? Se il codice è scritto nel file di intestazione, dovrei includere un file .cpp vuoto in modo che i file nel progetto rimangano coerenti?

risposta

14

Non aggiungerei file .cpp non necessari. Ogni file .cpp che si aggiunge deve essere compilato, il che rallenta il processo di compilazione.

In generale, l'utilizzo della classe richiede comunque solo il file di intestazione. Non vedo alcun vantaggio per un file .cpp "vuoto" per coerenza nel progetto.

+1

Non sono davvero d'accordo, il codice scritto all'interno di un'intestazione deve essere compilato tutte le volte che viene incluso mentre deve essere compilato una sola volta se si trova all'interno di un file sorgente (.c). Tuttavia sono d'accordo che è abbastanza conveniente e il tempo di compilazione non è un grosso problema per me. – Ben

+0

@Ben, l'ipotesi sarebbe che qualsiasi codice che verrebbe compilato nel file h sarebbe un codice di dimensioni in linea (o almeno un codice che potrebbe essere aggiunto a un'intestazione precompilata). Pertanto, il tempo di compilazione per il file h non sarebbe un problema. – kidnamedlox

+1

@kidnamedlox: esattamente. @ Ben: se includi codice di qualsiasi dimensione> rispetto a ciò che dovrebbe essere in linea, concordo sul fatto che un file .cpp sia una buona idea. È solo quando il codice è molto piccolo, penso che mettere un file .cpp vuoto solo per il piacere di un file .cpp non sia una buona pratica. –

8

No. Se non c'è nulla che deve essere nel file .cpp, non ne hai bisogno.

+0

A meno che non si abbia una dipendenza ciclica da qualche parte nel progetto, non per caso. – Chad

+0

Non sei sicuro di cosa intendi ... per favore spiega. – Grumdrig

+0

Se si ha una dipendenza ciclica che si desidera risolvere in questo modo, allora si ha qualcosa che deve essere nel file .cpp, quindi la risposta di Grumdrig rimane valida. – jalf

1

Regola del pollice, mantenere la classe correlata insieme nello stesso file. Classi molto diverse devono essere inserite nei propri file .hpp e .cpp. La ragione di ciò è che in grandi progetti hai fino a 10.000 classi e mettere quel numero di file di fronte all'utente e l'IDE di solito rompono le cose.

1

Esistono librerie molto utili e di successo, come molte di boost, che sono solo di intestazione.

1

Se alcune classi sono brevi e sembrano essere inlineabili, tendo a metterle tutte insieme in types.h - l'unica intestazione che non considero meritare un file .cpp.

Tuttavia, la maggior parte delle classi supera sia la possibilità di andare in intestazione solo, e la possibilità di andare in types.h.

Alcuni esempi da quello che faccio. Considero la classe per l'implementazione del vettore tridimensionale Vector3 per meritare il suo .h e .cpp, nonostante sia semplice. Ma lo Position non lo merita veramente; dopotutto, sarebbe addirittura un P.O.D. struttura, se non fosse per quel fastidioso getDistance() che mi piace implementato lì.

Quindi no, non tutte le classi meritano i file .cpp e .h. Ma la maggior parte lo fa, e quelli che sicuramente non riescono a stare in piedi in un colpo solo. Se sono così brevi da adattarsi all'intestazione da soli, o si accalcano insieme ad altre classi brevi o entrano nell'intestazione della classe a cui sono strettamente correlati.

1

La mia regola generale è che qualsiasi metodo di cui ho bisogno più di una riga di codice per esprimere va in un file .cpp.

Per un'ulteriore discussione di questo problema, è possibile controllare questa mia vecchia domanda: C++ code in header files. Non penso che la tua domanda sia un duplicato esatto, ma è abbastanza vicina da leggerla.

1

Vedere anche this question - i file di intestazione dovrebbero essere solo per le dichiarazioni.

Se il codice compilabile è incluso in più posizioni (dal tuo commento: "Potrei evitare di creare un file .cpp e scrivere il codice direttamente nel file di intestazione?"), verrà compilato ogni volta (anche se potresti avere intestazioni precompilate) e il linker risolverà (o meno) il codice oggetto gonfiato

Solo perché la definizione della classe è piccola non significa che dovrebbe essere nel file di intestazione a meno che la definizione è anche lo stesso che la dichiarazione - per esempio una classe virtuale pura o un tipo semplice, come indicato nel altra risposta

+0

Sfortunatamente, non tutti i compilatori supportano l'inlining dei link time e anche quelli che hanno un migliore supporto in fase di compilazione rispetto al link-time. Pertanto, è necessario inserire piccole funzioni critiche che si desidera inserire nelle intestazioni o eseguire contorsioni in fase di compilazione come Unity Builds. – Adisak

+0

Una definizione di classe ** deve ** essere in un'intestazione, se si intende utilizzare la classe in più unità di traduzione. Forse stavi pensando alle definizioni della classe _methods_? Quelli possono tranquillamente essere nel .cpp. Il motivo è perché il linker può risolvere funzioni e metodi al momento del collegamento, ma non intere classi. – MSalters

+0

@MSalters: vuoi dire che una dichiarazione ** di classe ** deve essere nell'intestazione. – quamrana

3

la sua davvero cavalli per i corsi:.

  • Header solo classi : ad es. modello classi
  • Intestazione e cpp : separa la dichiarazione dall'implementazione.
  • solo cpp: il tuo main() può vivere in uno di questi.

Il solo codice sorgente del file di intestazione è talvolta l'unico modo di scrivere modelli riutilizzabili. Vedi boost per molti esempi di questo.

Intestazione e cpp è più "normale". Separa la dichiarazione dall'implementazione e può accelerare la compilazione quando il compilatore non deve leggere più volte le implementazioni. Potresti voler iniziare qui e poi vedere come va l'implementazione e se il file cpp diventa vuoto puoi cancellarlo.
Un altro punto qui è che avrai il tuo #include "foo.h" nella parte superiore di foo.cpp per dimostrare che chiunque altro può farlo senza errori del compilatore.

Solo file Cpp. main() può vivere qui, e ho inserito le classi di test cppUnit in file come questo.

1

C'è un vantaggio per creare sempre un .cpp per ogni .h, anche quando il primo è vuoto: impone al momento della compilazione che i file di intestazione sono autonomi. Questo è in relazione con la guideline di includere foo.h prima in foo.cpp:

Con l'ordinamento preferita, se dir2/foo2.h omette qualsiasi necessario comprende, l'accumulo di dir/foo.cpp si romperà. Pertanto, questa regola garantisce che le interruzioni di compilazione vengano visualizzate per prime per le persone che lavorano su questi file, non per persone innocenti in altri pacchetti.