Domanda

Ho sempre usato un *.h file per la mia classe di definizioni, ma dopo la lettura di alcuni libreria boost codice, ho capito che tutti usano *.hpp.Ho sempre avuto un'avversione per tale estensione di file, penso soprattutto perché io non sono abituato.

Quali sono i vantaggi e gli svantaggi dell'utilizzo di *.hpp oltre *.h?

È stato utile?

Soluzione

Ecco un paio di ragioni per avere una diversa denominazione delle intestazioni C vs C ++:

  • Formattazione automatica del codice, potresti avere diverse linee guida per la formattazione del codice C e C ++. Se le intestazioni sono separate per estensione, puoi impostare il tuo editor per applicare automaticamente la formattazione appropriata
  • Denominazione, ho partecipato a progetti in cui c'erano librerie scritte in C e quindi i wrapper erano stati implementati in C ++. Poiché le intestazioni di solito avevano nomi simili, ovvero Feature.h vs Feature.hpp, erano facili da distinguere.
  • Inclusione, forse il tuo progetto ha versioni più appropriate disponibili scritte in C ++ ma stai usando la versione C (vedi punto sopra). Se le intestazioni prendono il nome dalla lingua in cui sono implementate, puoi facilmente individuare tutte le intestazioni C e verificare la presenza di versioni C ++.

Ricorda, C non è non C ++ e può essere molto pericoloso mescolare e abbinare se non sai cosa stai facendo. Dare un nome appropriato alle tue fonti ti aiuta a distinguere le lingue.

Altri suggerimenti

Uso .hpp perché voglio che l'utente distingua quali intestazioni sono intestazioni C ++ e quali intestazioni sono intestazioni C.

Questo può essere importante quando il tuo progetto utilizza entrambi i moduli C e C ++: Come qualcun altro ha spiegato prima di me, dovresti farlo con molta attenzione, e inizia con il " contratto " offri tramite l'estensione

.hpp: intestazioni C ++

(O .hxx, o .hh o altro)

Questa intestazione è solo per C ++.

Se sei in un modulo C, non provare nemmeno a includerlo. Non ti piacerà, perché non viene fatto alcuno sforzo per renderlo C-friendly (troppo andrebbe perso, come il sovraccarico delle funzioni, gli spazi dei nomi, ecc. Ecc.).

.h: intestazioni C / C ++ compatibili o pure C

Questa intestazione può essere inclusa sia da una fonte C che da una fonte C ++, direttamente o indirettamente.

Può essere incluso direttamente, essendo protetto dalla __cplusplus macro:

  • Il che significa che, dal punto di vista C ++, il codice C-compatibile sarà definito come extern "C".
  • Da un punto di vista C, tutto il codice C sarà chiaramente visibile, ma il codice C ++ sarà nascosto (perché non verrà compilato in un compilatore C).

Ad esempio:

#ifndef MY_HEADER_H
#define MY_HEADER_H

   #ifdef __cplusplus
      extern "C"
      {
   #endif

   void myCFunction() ;

   #ifdef __cplusplus
      } // extern "C"
   #endif

#endif // MY_HEADER_H

O potrebbe essere incluso indirettamente dalla corrispondente intestazione .hpp che lo racchiude con la <=> dichiarazione.

Ad esempio:

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP

extern "C"
{
#include "my_header.h"
}

#endif // MY_HEADER_HPP

e

#ifndef MY_HEADER_H
#define MY_HEADER_H

void myCFunction() ;

#endif // MY_HEADER_H

Ho sempre considerato l'intestazione .hpp come una sorta di portmanteau di .h e .cpp file ... un'intestazione che contiene anche dettagli di implementazione.

In genere quando ho visto (e uso) <=> come estensione, non esiste alcun file <=> corrispondente. Come altri hanno già detto, questa non è una regola dura e veloce, proprio come tendo a usare <=> file.

Non importa quale estensione usi. Uno dei due va bene.

Uso *.h per C e *.hpp per C ++.

MODIFICA [Aggiunto suggerimento di Dan Nissenbaum]:

Secondo una convenzione, i file .hpp vengono utilizzati quando i prototipi sono definiti nell'intestazione stessa. Tali definizioni nelle intestazioni sono utili nel caso di modelli, poiché il compilatore genera il codice per ciascun tipo solo all'istanza del modello. Pertanto, se non sono definiti nei file di intestazione, le loro definizioni non verranno risolte al momento del collegamento da altre unità di compilazione. Se il tuo progetto è un solo progetto C ++ che fa un uso pesante di modelli, questa convenzione potrebbe essere utile.

Alcune librerie di modelli che aderiscono a questa convenzione forniscono intestazioni con estensioni .hpp per indicare che non hanno file .cpp corrispondenti.

Alcune altre librerie di template usano un'altra convenzione, come usare .h per le intestazioni C e .hpp per C ++; un buon esempio sarebbe la libreria boost.

  

Citazione da Boost FAQ,

     

Le estensioni dei file comunicano il " digitare " del file, sia per gli umani   e ai programmi per computer. L'estensione '.h' è usata per l'intestazione C.   file e quindi comunica la cosa sbagliata sull'intestazione C ++   File. L'uso di nessuna estensione non comunica nulla e forza l'ispezione   del contenuto del file per determinare il tipo. Usando '.hpp' senza ambiguità   lo identifica come file di intestazione C ++ e funziona bene nella pratica reale.   (Rainer Deyke)

Di recente ho iniziato a utilizzare *.hpp per le intestazioni c ++.

Il motivo è che uso emacs come editor principale e questo entra automaticamente in modalità c quando carichi un file *.h e in modalità c ++ quando carichi un file <=>.

A parte questo fatto non vedo buoni motivi per scegliere <=> oltre <=> o viceversa.

Sto rispondendo a questo come un promemoria, per dare il punto del mio commento(s) su "user1949346" rispondere a questa stessa OP.


Così come molti già risposto:in entrambi i casi è bene.Seguito da enfatizza le proprie impressioni.

Introduttivo, come anche nel precedente denominato commenti detto, la mia opinione è C++ intestazione estensioni sono proposti per essere .h se vi è in realtà alcuna ragione contro di essa.

Poiché la norma ISO/IEC documenti di usare questa notazione di file di intestazione e non stringa corrispondente a .hpp si verifica anche nella loro lingua documentazioni su C++.

Ma ora sto puntando per una approvabili motivo per cui in entrambi i casi è ok, e soprattutto perché non è argomento del linguaggio.

Quindi qui si va.

Il C++ la documentazione (in realtà sto prendendo spunto dalla versione N3690) definisce che una intestazione deve essere conforme alla seguente sintassi:

2.9 i nomi di Intestazione

header-name:
    < h-char-sequence >
    " q-char-sequence "
h-char-sequence:
    h-char
    h-char-sequence h-char
h-char:
    any member of the source character set except new-line and >
q-char-sequence:
    q-char
    q-char-sequence q-char
q-char:
    any member of the source character set except new-line and "

Così come siamo in grado di estrarre da questa parte, il nome del file di intestazione può essere tutto ciò che è valido nel codice sorgente, troppo.Tranne contenente '\n' personaggi e a seconda se si tratta di essere inseriti <> non è consentito di contenere un >.O il altro senso se è incluso, ""-includere non può contenere un ".

In altre parole:se si ha un ambiente di sostegno nomi di file come prettyStupidIdea.>, sono come:

#include "prettyStupidIdea.>"

sarebbe valido, ma:

#include <prettyStupidIdea.>>

sarebbe invalida.L'altro modo intorno alla stessa.

E anche

#include <<.<>

sarebbe una valida includable nome del file di intestazione.

Anche questo sarebbe conforme a C++, sarebbe una bella bella idea stupida, tho.

Ed ecco perché .hpp è valido, troppo.

Ma non è un risultato dei comitati progettare decisioni per la lingua!!!

Quindi discutere di utilizzare .hpp è come farlo sulla .cc, .mm o che cosa mai altro ho letto in altri post su questo argomento.

Devo ammettere che non ho idea di dove .hpp è venuto da1, ma ci avrei scommesso un inventore di analisi strumento, IDE o qualcos'altro interessato con C++ arrivato a questa idea per ottimizzare alcuni processi interni o solo di inventare alcuni (probabilmente anche per loro necessariamente) le nuove convenzioni di denominazione.

Ma non è parte del linguaggio.

E ogni volta che uno decide di usarlo in questo modo.Può essere perché gli piace di più o perché alcune applicazioni del flusso di lavoro lo richiedono, non è mai2 è un requisito della lingua.Quindi chi dice "il pp è perché si è utilizzato il linguaggio C++", semplicemente è sbagliato per quel che riguarda le lingue definizione.

Il C++ permette di nulla rispetto al precedente paragrafo.E se c'è qualcosa che il comitato ha proposto di utilizzare, quindi si utilizza .h dal momento che questa è l'estensione citato in giudizio in tutti gli esempi di ISO documento.

Conclusione:

Finché non vedere/sentire alcuna necessità di utilizzare .h oltre .hpp o viceversa, non dovrebbe preoccuparsi.Perché entrambi sarebbero costituiscono un valido nome di intestazione della stessa qualità rispetto agli standard.E dunque tutto ciò che RICHIEDE per utilizzare .h o .hpp è un'ulteriore restrizione degli standard che potrebbe anche essere in contraddizione con altre restrizioni non sono conformi con gli altri.Ma come OP non parlare qualsiasi lingua aggiuntiva di restrizione, questa è l'unica corretta e approvabili risposta alla domanda

"*.h o *.hpp per le definizioni di classe"è:

Entrambi sono ugualmente corretti e applicabile fintanto che non vincoli esterni sono presenti.


1Da quello che so, a quanto pare, è la spinta quadro che si avvicinò con che .hpp estensione.

2Naturalmente non posso dire che alcune versioni future porterà con sé!

Preferisco .hpp per C ++ per chiarire sia agli editor che agli altri programmatori che si tratta di un'intestazione C ++ piuttosto che di un file di intestazione C.

C ++ (" C Plus Plus ") ha senso come .cpp

I file di intestazione con estensione .hpp non hanno lo stesso flusso logico.

Puoi chiamare le tue inclusioni come preferisci.

Devo solo specificare quel nome completo in #include.

Suggerisco che se lavori con C per usare .h e quando con C ++ per usare .hpp.

Alla fine è solo una convenzione.

Codegear C ++ Builder utilizza .hpp per i file di intestazione generati automagicamente dai file sorgente di Delphi e .h per il tuo " own " file di intestazione.

Quindi, quando scrivo un file header C ++ uso sempre .h.

In uno dei miei lavori nei primi anni '90, abbiamo usato rispettivamente .cc e .hh per i file sorgente e header. Lo preferisco ancora a tutte le alternative, probabilmente perché è più facile da scrivere.

Bjarne Stroustrup e Herb Sutter sono una dichiarazione a questa domanda, in loro C++ orientamenti di base su: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-source che è anche in riferimento ai più recenti cambiamenti nell'estensione standard C++11, C++14, etc.)

SF.1:Utilizzare un .cpp suffisso e i file di codice .h per i file di interfaccia se il vostro Y progetto non già seguire un'altra convenzione Ragione

È una lunga convenzione.Ma la coerenza è più importante, quindi se il progetto utilizza qualcosa di diverso, seguire che.Nota

La presente convenzione riflette un uso comune modello:Le intestazioni sono più spesso condiviso con il C per compilare sia come C e C++, che utilizza in genere .h e è più facile a nome di tutte le intestazioni .h invece di avere diverse estensioni per solo quelle intestazioni che sono destinate ad essere condivise con C.D'altra parte, file di implementazione raramente sono condivisi con la C e così deve essere in genere distinto dal .c file, quindi è normalmente migliore a nome di tutti C++ file di implementazione qualcos'altro (come ad esempio .cpp).

I nomi specifici .h e .il cpp non è richiesto (solo raccomandato come un di default) e altri nomi in uso diffuso.Esempi sono .hh, .C, e .cxx.L'uso di tali nomi, in modo equivalente.In questo documento si riferiscono .h e .cpp > come una scorciatoia per l'intestazione e file di implementazione, anche se l'effettiva l'estensione può essere diverso.

L'IDE (se si utilizza uno) può avere una forte opinione su basta.

Io non sono un grande fan di questa convenzione, perché se si utilizza una famosa libreria come boost, la vostra coerenza è già rotto e si dovrebbe utilizzare meglio .hpp.

Come molti hanno già menzionato, preferisco anche usare .hpp per le librerie solo intestazione che usano le classi / funzioni del modello. Preferisco usare .h per i file di intestazione accompagnati da file di origine .cpp o librerie condivise o statiche.

La maggior parte delle librerie che sviluppo sono basate su template e quindi devono essere solo header, ma quando scrivo applicazioni tendo a separare la dichiarazione dall'implementazione e finisco con i file .h e .cpp

Fortunatamente, è semplice.

Dovresti usare l'estensione .hpp se lavori con C ++ e dovresti usare .h per C o mescolare C e C ++.

Uso .h perché è quello che usa Microsoft e quello che crea il suo generatore di codice. Non c'è bisogno di andare contro il grano.

In " Il linguaggio di programmazione C ++, terza edizione di Bjarne Stroustrup " ;, il n & # 186; 1 libro C ++ da leggere, usa * .h. Quindi presumo che la migliore pratica sia usare * .h.

Tuttavia, anche * .hpp va bene!

È facile per gli strumenti e gli esseri umani distinguere qualcosa . Questo è tutto.

Nell'uso convenzionale (tramite boost, ecc.), .hpp sono in particolare le intestazioni C ++. D'altra parte, .h è per non C ++ - solo intestazioni (principalmente C). Rilevare con precisione la lingua del contenuto è generalmente difficile poiché ci sono molti casi non banali, quindi questa differenza rende spesso facile da scrivere uno strumento pronto per l'uso. Per gli umani, una volta ottenuto il convegno, è anche facile da ricordare e facile da usare.

Tuttavia, vorrei sottolineare che la convenzione stessa non sempre funziona, come previsto.

  • Non è forzato dalla specifica delle lingue , né C né C ++. Esistono molti progetti che non seguono la convenzione. Una volta che è necessario unirli (per mescolarli), può essere problematico.
  • .hh in sé non è l'unica scelta. Perché non .hxx o .cpp? (Sebbene comunque, di solito hai bisogno di almeno una regola convenzionale su nomi di file e percorsi.)

Uso personalmente sia <=> sia <=> nei miei progetti C ++. Non seguo la convenzione sopra perché:

  • Le lingue utilizzate da ciascuna parte dei progetti sono esplicitamente documentate. Nessuna possibilità di mescolare C e C ++ nello stesso modulo (directory). Ogni libreria di terze parti è tenuta a conformarsi a questa regola.
  • Sono inoltre documentate le specifiche di lingua conformi e i dialetti di lingua consentiti utilizzati dai progetti. (In effetti, documento anche l'origine delle funzionalità standard e la correzione dei bug ( sullo standard linguistico) in uso .) È un po 'più importante che distinguere le lingue utilizzate poiché è troppo soggetta a errori e il costo del test (ad esempio la compatibilità del compilatore) può essere significativo (complicato e richiede molto tempo) , specialmente in un progetto che è già in quasi puro C ++. I nomi dei file sono troppo deboli per gestirlo.
  • Anche per lo stesso dialetto C ++, potrebbero esserci proprietà più importanti adatte alla differenza. Ad esempio, vedi la convenzione di seguito.
  • I nomi dei file sono essenzialmente pezzi di fragili metadati. La violazione della convenzione non è così facile da rilevare. Per essere stabili nel gestire il contenuto, uno strumento alla fine non dovrebbe dipendere solo dai nomi. La differenza tra le estensioni è solo un suggerimento. Anche gli strumenti che lo utilizzano non dovrebbero comportarsi sempre allo stesso modo, ad es. rilevamento della lingua di <=> file su github.com. (Potrebbe esserci qualcosa nei commenti come shebang affinché questi file sorgente siano metadati migliori, ma non è nemmeno convenzionale come i nomi dei file, quindi non è affidabile in generale.)

Di solito uso <=> su intestazioni C ++ e le intestazioni dovrebbero essere usate (mantenute) in modo solo intestazioni , ad es. come librerie di modelli. Per le altre intestazioni in <=>, esiste un file <=> corrispondente come implementazione o è un'intestazione non C ++. Quest'ultimo è banale per differenziare i contenuti dell'intestazione dagli umani (o dagli strumenti con metadati espliciti incorporati, se necessario).

L'estensione del file sorgente potrebbe avere un significato per il tuo sistema di compilazione, ad esempio potresti avere una regola nel tuo makefile per .cpp o .c file, oppure il tuo compilatore (ad es. Microsoft cl.exe) potrebbe compilare il file come C o C ++ a seconda dell'estensione.

Poiché è necessario fornire l'intero nome file alla direttiva #include, l'estensione del file di intestazione è irrilevante. Se lo desideri, puoi includere un file /P in un altro file sorgente, perché è solo un'inclusione testuale. Il compilatore potrebbe avere un'opzione per scaricare l'output preelaborato che lo chiarirà (Microsoft: /E per preelaborare su file, stdout per preelaborare su /EP, #line per omettere /C direttive, .hpp per conservare i commenti)

Potresti scegliere di utilizzare <=> per i file che sono rilevanti solo per l'ambiente C ++, ovvero usano funzionalità che non verranno compilate in C.

Non vi è alcun vantaggio in nessuna particolare estensione, a parte quello che può avere un significato diverso per te, il compilatore e / o i tuoi strumenti. header.h è un'intestazione valida. header.hpp è un'intestazione valida. header.hh è un'intestazione valida. header.hx è un'intestazione valida. h.header è un'intestazione valida. this.is.not.a.valid.header è un'intestazione valida nel rifiuto. ihjkflajfajfklaf è un'intestazione valida. Finché il compilatore può analizzare correttamente il nome e il file system lo supporta, è un'intestazione valida e l'unico vantaggio della sua estensione è ciò che si legge in esso.

Detto questo, essere in grado di formulare con precisione ipotesi basate sull'estensione è molto utile, quindi sarebbe saggio usare un insieme di regole facilmente comprensibili per i file di intestazione. Personalmente, preferisco fare qualcosa del genere:

  1. Se esistono già delle linee guida stabilite, seguirle per evitare confusione.
  2. Se tutti i file di origine nel progetto sono nella stessa lingua, utilizzare .h. Non c'è ambiguità.
  3. Se alcune intestazioni sono compatibili con più lingue, mentre altre sono compatibili solo con una sola lingua, le estensioni si basano sulla lingua più restrittiva con cui un'intestazione è compatibile. Un'intestazione compatibile con C, o con entrambi gli amplificatori C &; C ++, ottiene .hpp, mentre un'intestazione compatibile con C ++ ma non C ottiene .hh o .tpp o qualcosa del genere.

Questo, ovviamente, non è che uno dei molti modi per gestire le estensioni e non puoi necessariamente fidarti della tua prima impressione anche se le cose sembrano semplici. Ad esempio, ho visto la menzione dell'utilizzo di .hxx per le intestazioni normali e <=> per le intestazioni che contengono solo definizioni per le funzioni dei membri della classe con template, con <=> file che definiscono le classi con template inclusi i <=> file che definiscono le loro funzioni membro (anziché l'intestazione <=> contenente direttamente sia la dichiarazione di funzione che la definizione). Per un altro esempio, molte persone riflettono sempre il linguaggio dell'intestazione nella sua estensione, anche quando non c'è possibilità di ambiguità; per loro, <=> è sempre un'intestazione C e <=> (o <=>, o <=>, ecc.) è sempre un'intestazione C ++. E ancora una volta, alcune persone usano <=> per & Quot; intestazione associata a un file sorgente & Quot; e <=> per " header con tutte le funzioni definite inline " ;.

Considerando ciò, il vantaggio principale risiederebbe nel nominare in modo coerente le intestazioni nello stesso stile e renderlo facilmente visibile a chiunque stia esaminando il tuo codice. In questo modo, chiunque abbia familiarità con il tuo solito stile di codifica sarà in grado di determinare cosa intendi con una determinata estensione con una rapida occhiata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top