O que deve e o que não deve estar em um arquivo de cabeçalho? [fechadas]

57

Quais coisas absolutamente nunca devem ser incluídas em um arquivo de cabeçalho?

Se, por exemplo, eu estiver trabalhando com um formato padrão do setor documentado que tenha muitas constantes, é uma boa prática defini-las em um arquivo de cabeçalho (se eu estiver escrevendo um analisador para esse formato)?

Quais funções devem entrar no arquivo de cabeçalho? Quais funções não deveriam?

    
por Moshe Magnes 06.10.2012 / 10:13
fonte

5 respostas

46

O que colocar nos cabeçalhos:

  • O conjunto mínimo de diretivas #include que são necessárias para tornar o cabeçalho compilável quando o cabeçalho é incluído em algum arquivo de origem.
  • Definições de símbolos do pré-processador de itens que precisam ser compartilhados e que só podem ser executados por meio do pré-processador. Mesmo em C, os símbolos do pré-processador são mantidos no mínimo.
  • Encaminhar declarações de estruturas necessárias para tornar as definições de estrutura, protótipos de função e declarações de variáveis globais no corpo do cabeçalho compilável.
  • Definições de estruturas de dados e enumerações que são compartilhadas entre vários arquivos de origem.
  • Declarações de funções e variáveis cujas definições serão visíveis para o vinculador.
  • Definições da função inline, mas tenha cuidado aqui.

O que não pertence em um cabeçalho:

  • Diretivas #include gratuitas. Aqueles gratuitos incluem causar recompilação de coisas que não precisam ser recompiladas, e às vezes podem fazer com que um sistema não possa ser compilado. Não #include um arquivo em um cabeçalho se o próprio cabeçalho não precisar desse outro arquivo de cabeçalho.
  • Símbolos de pré-processador cuja intenção poderia ser realizada por algum mecanismo, qualquer mecanismo, diferente do pré-processador.
  • Muitas e muitas definições de estrutura. Divida-os em cabeçalhos separados.
  • Definições em linha de funções que exigem #include adicionais, que estão sujeitas a alterações ou que são muito grandes. Essas funções inline devem ter pouco ou nenhum fan-out, e se elas tiverem fan-out, elas devem ser localizadas para coisas definidas no cabeçalho.

O que constitui o conjunto mínimo de #include declarações?

Isso acaba sendo uma questão não trivial. Uma definição TL; DR: Um arquivo de cabeçalho deve incluir os arquivos de cabeçalho que definem diretamente cada um dos tipos usados diretamente ou que declaram diretamente cada uma das funções usadas no arquivo de cabeçalho em questão, mas não devem incluir mais nada. Um ponteiro ou tipo de referência C ++ não se qualifica como uso direto; referências para frente são preferidas.

Há um lugar para uma diretiva #include gratuita, e isso está em um teste automatizado. Para cada arquivo de cabeçalho em um pacote de software, eu automaticamente gero e, em seguida, compilo o seguinte:

#include "path/to/random/header_under_test"
int main () { return 0; }

A compilação deve estar limpa (ou seja, livre de quaisquer avisos ou erros). Avisos ou erros referentes a tipos incompletos ou desconhecidos significam que o arquivo de cabeçalho em teste possui algumas diretivas #include ausentes e / ou declarações encaminhadas ausentes. Note bem: só porque o teste passa não significa que o conjunto de diretivas #include seja suficiente, e muito menos o mínimo.

    
por 06.10.2012 / 16:39
fonte
13

Além do que já foi dito.

Os arquivos H devem conter sempre:

  • Documentação do código-fonte !!! No mínimo, qual é o propósito dos vários parâmetros e valores de retorno das funções.
  • Guardas de cabeçalho, #ifndef MYHEADER_H #define MYHEADER_H ... #endif

Os arquivos H nunca devem conter:

  • Qualquer forma de alocação de dados.
  • Definições de funções. Funções inline podem ser raras exceções em alguns casos.
  • Qualquer coisa chamada static .
  • Typedefs, #defines ou constantes que não têm relevância para o restante do aplicativo.

(Eu também diria que nunca há qualquer razão para usar variáveis globais / externas não constantes, em qualquer lugar, mas isso é uma discussão para outro post.)

    
por 08.10.2012 / 15:08
fonte
4

Eu provavelmente nunca diria nunca, mas as declarações que geram dados e códigos à medida que são analisadas não devem estar em um arquivo .h.

Macros, funções embutidas e modelos podem parecer dados ou código, mas não geram código à medida que são analisados, mas sim quando são usados. Esses itens geralmente precisam ser usados em mais de um .c ou .cpp, então eles pertencem ao .h.

Na minha opinião, um arquivo de cabeçalho deve ter a interface prática mínima para um .c ou .cpp correspondente. A interface pode incluir #defines, classe, typedef, definições de estruturas, protótipos de funções e definições externas menos preferidas para variáveis globais. No entanto, se uma declaração for usada em apenas um arquivo de origem, ela provavelmente deve ser excluída do .h e estar contida no arquivo de origem.

Alguns podem discordar, mas meu critério pessoal para arquivos .h é que eles #incluem todos os outros arquivos .h que precisam ser compilados. Em alguns casos, isso pode ser um monte de arquivos, por isso temos alguns métodos eficazes para reduzir dependências externas como declarações de encaminhamento para classes que nos permitem usar ponteiros para objetos de uma classe sem incluir o que poderia ser uma grande árvore de arquivos include. / p>     

por 06.10.2012 / 22:14
fonte
3

O arquivo de cabeçalho deve ter a seguinte organização:

  • tipo e definições constantes
  • declarações de objetos externos
  • declarações de função externa

Arquivos de cabeçalho nunca devem conter definições de objetos, apenas definições de tipos e declarações de objetos.

    
por 06.10.2012 / 11:40
fonte
0

Declarações que geram dados e códigos à medida que são analisadas, não devem estar em um arquivo .h . No que diz respeito ao meu ponto de vista, um arquivo de cabeçalho deve ter apenas a interface prática mínima para um .c ou .cpp correspondente.

    
por 01.03.2014 / 17:08
fonte

Tags