* .h ou * .hpp para suas definições de classe


555

Eu sempre usei um *.harquivo para minhas definições de classe, mas depois de ler alguns códigos da biblioteca de aumento, percebi que todos eles usam *.hpp. Eu sempre tive aversão a essa extensão de arquivo, principalmente porque não estou acostumada.

Quais são as vantagens e desvantagens do uso *.hppexcessivo *.h?

Respostas:


528

Aqui estão alguns motivos para ter nomes diferentes de cabeçalhos C vs C ++:

  • Formatação automática de código, você pode ter diretrizes diferentes para formatar o código C e C ++. Se os cabeçalhos estiverem separados por extensão, você poderá configurar seu editor para aplicar a formatação apropriada automaticamente
  • Nomeando, estive em projetos em que havia bibliotecas escritas em C e, em seguida, os wrappers foram implementados em C ++. Como os cabeçalhos geralmente tinham nomes semelhantes, ou seja, Feature.h vs Feature.hpp, eles eram fáceis de distinguir.
  • Inclusão, talvez o seu projeto tenha versões mais apropriadas disponíveis, escritas em C ++, mas você esteja usando a versão C (veja o ponto acima). Se os cabeçalhos tiverem o nome do idioma em que são implementados, você poderá identificar facilmente todos os cabeçalhos em C e verificar as versões em C ++.

Lembre-se, C não é C ++ e pode ser muito perigoso misturar e combinar, a menos que você saiba o que está fazendo. Nomear suas fontes adequadamente ajuda a diferenciar os idiomas.


234

Uso .hpp porque quero que o usuário diferencie quais cabeçalhos são C ++ e quais são C.

Isso pode ser importante quando o seu projeto estiver usando os módulos C e C ++: Como alguém explicado antes de mim, você deve fazê-lo com muito cuidado e começa com o "contrato" que você oferece através da extensão

.hpp: cabeçalhos C ++

(Ou .hxx, ou .hh, ou o que for)

Este cabeçalho é apenas para C ++.

Se você estiver em um módulo C, nem tente incluí-lo. Você não vai gostar, porque não é feito nenhum esforço para torná-lo compatível com C (muito seria perdido, como sobrecarga de funções, espaços para nome, etc. etc.).

.h: cabeçalhos C puros ou compatíveis com C / C ++

Esse cabeçalho pode ser incluído por uma fonte C e uma fonte C ++, direta ou indiretamente.

Pode ser incluído diretamente, sendo protegido pela __cplusplusmacro:

  • O que significa que, do ponto de vista de C ++, o código compatível com C será definido como extern "C".
  • Do ponto de vista C, todo o código C estará claramente visível, mas o código C ++ ficará oculto (porque não será compilado em um compilador C).

Por exemplo:

#ifndef MY_HEADER_H
#define MY_HEADER_H

   #ifdef __cplusplus
      extern "C"
      {
   #endif

   void myCFunction() ;

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

#endif // MY_HEADER_H

Ou pode ser incluído indiretamente pelo cabeçalho .hpp correspondente, que o inclui com a extern "C"declaração.

Por exemplo:

#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

3
Isso não é habitual em muitos projetos C ++. Os arquivos .h são usados ​​para coisas muito não-C'ish.
einpoklum

4
@einpoklum: Claro. Mas eu tento evitar o comportamento "Monkey See Monkey Do". No caso atual, ambas as extensões (e outras) estão disponíveis, então eu tento fazê-las contar. Ter este contrato com código compartilhado com os clientes é muito útil: todo mundo (ou seja, centenas de desenvolvedores) sabe que os arquivos ".H" devem ser usados ​​pelos clientes usando um compilador C, portanto, não há dúvidas sobre o que pode acontecer lá ou não. E todos (incluindo os clientes) sabem que os arquivos ".HPP" nunca tentarão ser compatíveis com C. Todo mundo ganha.
paercebal

4
@ paercebal, então você está sugerindo .H em vez de .h e .HPP sobre .hpp ?
Geof Sawaya

6
@ GeofSawaya: Não, desculpe. É um hábito. Ao escrever artigos, uso extensões em maiúsculas para diferenciar arquivos por tipo, como "arquivos .HPP". Mas as extensões dos arquivos reais que estão no meu disco rígido são sempre em letras minúsculas, mesmo no nome não é, como "MyClass.hpp" ou "module.hpp"
paercebal

4
Obrigado, @paercebal. Eu estava ficando pedante
Geof Sawaya

48

Eu sempre considerei o .hppcabeçalho uma espécie de portmanteau .he .cpparquivos ... um cabeçalho que também contém detalhes de implementação.

Normalmente, quando vejo (e uso) .hppcomo uma extensão, não há .cpparquivo correspondente . Como já foi dito, essa não é uma regra rígida, exatamente como eu uso .hpparquivos.


31

Não importa qual extensão você usa. Qualquer um está bem.

Eu uso *.hpara C e *.hpppara C ++.


23

EDIT [Adicionado sugestão de Dan Nissenbaum]:

Por uma convenção, os arquivos .hpp são usados ​​quando os protótipos são definidos no próprio cabeçalho. Essas definições nos cabeçalhos são úteis no caso de modelos, pois o compilador gera o código para cada tipo apenas na instanciação do modelo. Portanto, se eles não estiverem definidos nos arquivos de cabeçalho, suas definições não serão resolvidas no momento do link de outras unidades de compilação. Se o seu projeto for apenas em C ++ e fizer uso intenso de modelos, essa convenção será útil.

Certas bibliotecas de modelos que aderem a esta convenção fornecem aos cabeçalhos extensões .hpp para indicar que eles não têm arquivos .cpp correspondentes.

outra convenção é usar .h para cabeçalhos C e .hpp para C ++; Um bom exemplo seria a biblioteca de impulso.

Citações das perguntas frequentes do Boost,

As extensões de arquivo comunicam o "tipo" do arquivo, tanto para humanos quanto para programas de computador. A extensão '.h' é usada para arquivos de cabeçalho C e, portanto, comunica a coisa errada sobre os arquivos de cabeçalho C ++. O uso de nenhuma extensão não comunica nada e força a inspeção do conteúdo do arquivo para determinar o tipo. O uso de '.hpp' o identifica sem ambiguidade como arquivo de cabeçalho C ++ e funciona bem na prática real. (Rainer Deyke)


Nada disso é verdade, não faz diferença se o arquivo é .h ou .hpp quando se trata de geração ou vinculação de código.
Mark Ingram

não é apenas uma questão de convenção? A biblioteca C ++ std fornece todos os seus cabeçalhos sem nenhuma extensão. usar ".hpp" indica apenas que os protótipos estão definidos no mesmo arquivo e não haverá nenhum arquivo .cpp correspondente.
precisa

5
Acho que essa resposta é útil, com a exceção de que está faltando uma frase muito simples, mas importante: "por convenção, não pelas regras da linguagem" (em algum lugar).
Dan Nissenbaum

13

Recentemente, comecei a usar *.hpppara cabeçalhos de c ++.

O motivo é que eu uso o emacs como meu editor principal e ele entra automaticamente no modo c quando você carrega um *.harquivo e no modo c ++ - quando você carrega um *.hpparquivo.

Além desse fato, não vejo boas razões para escolher *.hmais *.hppou vice-versa.


7
Pessoalmente, acho que o destaque em C ++ é uma boa ideia, mesmo nos cabeçalhos em C. Eu já estive nos dois extremos da situação em que alguém deseja incluir o cabeçalho C do C ++, mas ele usa uma palavra-chave C ++ como nome de parâmetro ... #
3160 Steve

12

Estou respondendo a isso como um lembrete, para citar meus comentários sobre a resposta "user1949346" desse mesmo OP.


Então, como muitos já responderam: de qualquer maneira está bem. Seguido por enfatiza suas próprias impressões.

Introdutório, como também nos comentários nomeados anteriores declarados, minha opinião é que as C++extensões de cabeçalho são propostas, .hcaso não haja realmente nenhuma razão contra isso.

Como os documentos ISO / IEC usam essa notação de arquivos de cabeçalho e nenhuma correspondência de string .hppocorre mesmo nas documentações de idiomas deles C++.

Mas agora estou buscando uma razão aprovável PORQUE de qualquer maneira está ok, e especialmente porque não é assunto da linguagem em si.

Aqui vamos nos.

A C++documentação (na verdade, estou tomando referência da versão N3690) define que um cabeçalho deve estar em conformidade com a seguinte sintaxe:

2.9 Nomes de cabeçalho

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 "

Portanto, como podemos extrair desta parte, o nome do arquivo de cabeçalho também pode ser válido no código-fonte. Exceto por conter '\n'caracteres e, dependendo se ele deve ser incluído, <>não é permitido que contenha a >. Ou, caso contrário, se for incluído por ""-include, não será permitido conter a ".

Em outras palavras: se você tinha um ambiente que suporta nomes de arquivos como prettyStupidIdea.>, inclua:

#include "prettyStupidIdea.>"

seria válido, mas:

#include <prettyStupidIdea.>>

seria inválido. O contrário é o mesmo.

E até mesmo

#include <<.<>

seria um nome de arquivo de cabeçalho inclusivo válido.

Mesmo isso seria conforme C++, seria uma idéia muito estúpida, tho.

E é por isso que também .hppé válido.

Mas não é um resultado dos comitês que elaboram decisões para o idioma!

Portanto, discutir sobre o uso .hppé o mesmo que fazê-lo .cc, .mmou o que mais eu li em outros posts sobre esse tópico.

Eu tenho que admitir que não tenho idéia de onde .hppveio 1 , mas eu apostaria que um inventor de alguma ferramenta de análise, IDE ou outra coisa preocupada C++chegou a essa idéia para otimizar alguns processos internos ou apenas para inventar alguns (provavelmente mesmo para eles necessariamente ) novas convenções de nomenclatura.

Mas isso não faz parte do idioma.

E sempre que alguém decide usá-lo dessa maneira. Pode ser que ele goste mais ou porque algumas aplicações do fluxo de trabalho exijam, nunca 2 é um requisito da linguagem. Portanto, quem diz que "o pp é porque é usado com C ++" simplesmente está errado em relação à definição de linguagens.

C ++ permite qualquer coisa que respeite o parágrafo anterior. E se houver algo que o comitê se proponha a usar, ele será usado, .hpois essa é a extensão processada em todos os exemplos do documento ISO.

Conclusão:

Contanto que você não veja / sinta nenhuma necessidade de usar .hover .hppou vice-versa, não deve se preocupar. Porque ambos formariam um nome de cabeçalho válido com a mesma qualidade em relação ao padrão. E, portanto, qualquer coisa que EXIGE que você use .hou .hppé uma restrição adicional do padrão que pode até estar em contradição com outras restrições adicionais que não estão em conformidade. Mas como o OP não menciona nenhuma restrição adicional de idioma, esta é a única resposta correta e aprovada para a pergunta

" * .h ou * .hpp para suas definições de classe " é:

Ambos são igualmente corretos e aplicáveis, desde que não haja restrições externas.


1 Pelo que sei, aparentemente, é a estrutura de impulso que surgiu com essa .hppextensão.

2 É claro que não posso dizer o que algumas versões futuras trarão com ele!


7

Eu prefiro .hpp para C ++ para deixar claro para os editores e para outros programadores que é um cabeçalho C ++ em vez de um arquivo de cabeçalho C.


6

C ++ ("C Plus Plus") faz sentido como .cpp

Ter arquivos de cabeçalho com extensão .hpp não tem o mesmo fluxo lógico.


6

Você pode ligar para suas inclusões como quiser.

Só precisa especificar esse nome completo no #include.

Sugiro que, se você trabalha com C para usar .he quando estiver usando C ++ .hpp.

É no final apenas uma convenção.


5

O Codegear C ++ Builder usa .hpp para arquivos de cabeçalho gerados automaticamente a partir de arquivos de origem Delphi e arquivos .h para seus "próprios" arquivos de cabeçalho.

Então, quando estou escrevendo um arquivo de cabeçalho C ++, sempre uso .h.


5

Em um dos meus trabalhos no início dos anos 90, usamos .cc e .hh para arquivos de origem e cabeçalho, respectivamente. Eu ainda prefiro isso entre todas as alternativas, provavelmente porque é mais fácil digitar.


5

Bjarne Stroustrup e Herb Sutter têm uma declaração para esta pergunta em suas diretrizes principais do C ++, encontradas em: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-source, que também se refere às alterações mais recentes na extensão padrão (C ++ 11, C ++ 14, etc.)

SF.1: Use um sufixo .cpp para arquivos de código e .h para arquivos de interface se o seu projeto Y ainda não seguir outra convenção Motivo

É uma convenção de longa data. Mas a consistência é mais importante; portanto, se o seu projeto usa outra coisa, siga-o. Nota

Essa convenção reflete um padrão de uso comum: os cabeçalhos são mais frequentemente compartilhados com C para compilar como C ++ e C, que normalmente usa .h, e é mais fácil nomear todos os cabeçalhos .h em vez de ter extensões diferentes apenas para os cabeçalhos destinados para serem compartilhados com C. Por outro lado, os arquivos de implementação raramente são compartilhados com C e, portanto, geralmente devem ser diferenciados dos arquivos .c, portanto, normalmente é melhor nomear todos os arquivos de implementação do C ++ de outra forma (como .cpp).

Os nomes específicos. He .cpp não são necessários (apenas recomendado como padrão) e outros nomes são amplamente utilizados. Exemplos são .hh, .C e .cxx. Use esses nomes de forma equivalente. Neste documento, nos referimos a. Hepp. Como uma abreviação de arquivos de cabeçalho e implementação, mesmo que a extensão real possa ser diferente.

Seu IDE (se você usar um) pode ter opiniões fortes sobre o suficiente.

Eu não sou um grande fã desta convenção, porque se você estiver usando uma biblioteca popular como o boost, sua consistência já está quebrada e você deve usar melhor o .hpp.


4

Como muitos aqui já mencionaram, também prefiro usar .hpp para bibliotecas somente de cabeçalho que usam classes / funções de modelo. Prefiro usar .h para arquivos de cabeçalho acompanhados por arquivos de origem .cpp ou bibliotecas compartilhadas ou estáticas.

A maioria das bibliotecas que desenvolvo são baseadas em modelos e, portanto, precisam ser apenas de cabeçalho, mas ao escrever aplicativos, costumo separar a declaração da implementação e acabar com os arquivos .h e .cpp


3

Felizmente, é simples.

Você deve usar a extensão .hpp se estiver trabalhando com C ++ e deve usar .h para C ou misturar C e C ++.


2

Eu uso .h porque é isso que a Microsoft usa e o que seu gerador de código cria. Não há necessidade de ir contra a corrente.


não em todos os lugares, em um monte de exemplos (eq WINDDK) eles usam .hpp
pântano-de manobra

13
Eu não chamaria a Microsoft de 'grão' quando se trata de C ++.
developerbmw

@Brett é quando esse é o seu trabalho. E mesmo que não seja, é um compilador popular.
Mark Ransom

@ MarkRansom Eu estava me referindo mais ao histórico da Microsoft de usar C. O IMO VC ++ é um excelente compilador.
developerbmw

1
@developerbmw Eu diria que o MSVC é o principal para os programas do Windows e o GCC é o principal para os programas * nix, pessoalmente. Eles são os que a maioria dos outros compiladores dessas plataformas tendem a permanecer compatíveis, pelo que sei.
Justin Time - Restabelece Monica

1

Em "A linguagem de programação C ++, terceira edição de Bjarne Stroustrup", o livro C ++ de leitura obrigatória nº1, ele usa * .h. Portanto, presumo que a melhor prática seja usar * .h.

No entanto, * .hpp também é bom!


1
Se alguém escreveu um livro sobre algo que aprendeu de outros que o aprenderam de outro livro (talvez com a mesma sorte), escrito por alguém que talvez tivesse a fonte principal disponível, é isso que eles estão fazendo, exceto a marca para sendo as melhores práticas.
Dhein

Apenas para mencionar: eu realmente votei isso. Mas eu teria votado positivamente, se dissesse "ISO / IEC N3690" ou qualquer outro rascunho de C ++, não seja "A linguagem de programação C ++, terceira edição de Bjarne Stroustrup". Embora isso tenha sido um ponto válido, uma vez que não há menção .hppà própria linguagem.
Dhein

9
@zaibis, você sabe que Bjarne Stroustrup inventou C ++, certo?
tumtumtum

@tumtumtum: admitiu, eu não estava ciente disso. Mas de qualquer maneira, mesmo nesse caso, ainda é o documento do comitê, mantendo o padrão, que é a referência a ser tomada. Mesmo que ele seja o inventor da linguagem, não é mais uma decisão dele. Portanto, embora isso torne a resposta mais valiosa, ainda não é um raciocínio válido.
Dhein

1

É fácil para ferramentas e humanos diferenciarem algo . É isso aí.

No uso convencional (por impulso, etc), .hppsão especificamente cabeçalhos de C ++. Por outro lado, .hé para cabeçalhos não C ++ - apenas (principalmente C). Detectar com precisão o idioma do conteúdo geralmente é difícil, uma vez que existem muitos casos não triviais, portanto essa diferença geralmente facilita a gravação de uma ferramenta pronta para uso. Para os seres humanos, depois de obter a convenção, também é fácil de lembrar e fácil de usar.

No entanto, gostaria de salientar que a convenção em si nem sempre funciona, como esperado.

  • Não é forçado pela especificação de linguagens , nem C nem C ++. Existem muitos projetos que não seguem a convenção. Depois de mesclar (misturar) eles, pode ser problemático.
  • .hppem si não é a única escolha. Por que não .hhou .hxx? (De qualquer forma, você geralmente precisa de pelo menos uma regra convencional sobre nomes de arquivos e caminhos.)

Eu pessoalmente uso os dois .he .hppnos meus projetos C ++. Não sigo a convenção acima porque:

  • Os idiomas usados ​​por cada parte dos projetos são explicitamente documentados. Sem chance de misturar C e C ++ no mesmo módulo (diretório). Todas as bibliotecas de terceiros precisam estar em conformidade com esta regra.
  • As especificações de idiomas conformes e os dialetos permitidos usados ​​pelos projetos também são documentados. (De fato, eu até documento a origem dos recursos padrão e da correção de bugs (no idioma padrão) que está sendo usada .) Isso é um pouco mais importante do que distinguir os idiomas usados, pois é muito suscetível a erros e o custo do teste (por exemplo, compatibilidade do compilador) pode ser significativa (complicada e demorada), especialmente em um projeto que já está em C ++ quase puro . Os nomes de arquivos são muito fracos para lidar com isso.
  • Mesmo para o mesmo dialeto C ++, pode haver propriedades mais importantes adequadas à diferença. Por exemplo, veja a convenção abaixo.
  • Os nomes de arquivos são essencialmente partes de metadados frágeis. A violação da convenção não é tão fácil de detectar. Para ser estável ao lidar com o conteúdo, uma ferramenta deve, eventualmente, não depender apenas de nomes. A diferença entre extensões é apenas uma dica. As ferramentas que o utilizam também não devem se comportar o mesmo o tempo todo, por exemplo, detecção de idioma de .harquivos no github.com. (Pode haver algo nos comentários, como shebang, para que esses arquivos de origem sejam melhores metadados, mas nem mesmo é convencional como nomes de arquivos, portanto, também não é confiável em geral.)

Eu costumo usar .hppem cabeçalhos C ++ e os cabeçalhos devem ser usados ​​(mantidos) de maneira somente cabeçalho , por exemplo, como bibliotecas de modelos. Para outros cabeçalhos .h, existe um .cpparquivo correspondente como implementação ou é um cabeçalho não C ++. O último é trivial de se diferenciar pelo conteúdo do cabeçalho por humanos (ou por ferramentas com metadados explícitos incorporados, se necessário).


0

A extensão do arquivo de origem pode ter significado para o seu sistema de compilação, por exemplo, você pode ter uma regra em seu makefile para .cppou .carquivos, ou seu compilador (por exemplo, Microsoft cl.exe) pode compilar o arquivo como C ou C ++, dependendo da extensão.

Como você precisa fornecer o nome do arquivo inteiro para a #includediretiva, a extensão do arquivo de cabeçalho é irrelevante. Você pode incluir um .carquivo em outro arquivo de origem, se quiser, porque é apenas uma inclusão textual. Seu compilador pode ter uma opção para despejar a saída pré-processada que tornará isso claro (Microsoft: /Ppara pré-processar para arquivar, /Epara pré-processar para stdout, /EPpara omitir #linediretivas, /Cpara reter comentários)

Você pode optar por usar .hpparquivos relevantes apenas para o ambiente C ++, ou seja, eles usam recursos que não serão compilados em C.


0

Não há vantagem em nenhuma extensão específica, exceto aquela que pode ter um significado diferente para você, o compilador e / ou suas ferramentas. header.hé um cabeçalho válido. header.hppé um cabeçalho válido. header.hhé um cabeçalho válido. header.hxé um cabeçalho válido. h.headeré um cabeçalho válido. this.is.not.a.valid.headeré um cabeçalho válido em negação. ihjkflajfajfklafé um cabeçalho válido. Contanto que o nome possa ser analisado corretamente pelo compilador e o sistema de arquivos o suporte, é um cabeçalho válido, e a única vantagem de sua extensão é o que se lê nele.

Dito isto, ser capaz de fazer suposições precisas com base na extensão é muito útil, portanto, seria aconselhável usar um conjunto de regras de fácil compreensão para os arquivos de cabeçalho. Pessoalmente, prefiro fazer algo assim:

  1. Se já existem diretrizes estabelecidas, siga-as para evitar confusões.
  2. Se todos os arquivos de origem no projeto forem para o mesmo idioma, use .h. Não há ambiguidade.
  3. Se alguns cabeçalhos são compatíveis com vários idiomas, enquanto outros são compatíveis apenas com um único idioma, as extensões são baseadas no idioma mais restritivo ao qual um cabeçalho é compatível. Um cabeçalho compatível com C, ou com ambos C & C ++, recebe .h, enquanto um cabeçalho compatível com C ++, mas não C recebe .hppou .hhou algo do tipo.

É claro que essa é apenas uma das muitas maneiras de lidar com extensões, e você não pode necessariamente confiar na sua primeira impressão, mesmo que as coisas pareçam simples. Por exemplo, vi menção de uso .hpara cabeçalhos normais e .tpppara cabeçalhos que contêm apenas definições para funções de membro de classe com modelo, com .harquivos que definem classes com modelo, incluindo os .tpparquivos que definem suas funções de membro (em vez do .hcabeçalho que contém diretamente os declaração de função e definição). Por outro exemplo, muitas pessoas sempre refletem o idioma do cabeçalho em sua extensão, mesmo quando não há chance de ambiguidade; para eles, .hsempre é um cabeçalho C e .hpp(ou .hh, ou.hxx, etc.) é sempre um cabeçalho C ++. E mais uma vez, algumas pessoas usam .hpara "cabeçalho associado a um arquivo de origem" e .hpp"cabeçalho com todas as funções definidas em linha".

Considerando isso, a principal vantagem seria nomear seus cabeçalhos de maneira consistente no mesmo estilo e tornar esse estilo facilmente aparente para qualquer pessoa que examinasse seu código. Dessa forma, qualquer pessoa familiarizada com o seu estilo de codificação usual poderá determinar o que você quer dizer com qualquer extensão com apenas um olhar superficial.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.