Que coisas absolutamente nunca devem ser incluídas em um arquivo de cabeçalho?
Se, por exemplo, estou trabalhando com um formato padrão do setor documentado que possui muitas constantes, é uma boa prática defini-las em um arquivo de cabeçalho (se estou escrevendo um analisador para esse formato)?
Quais funções devem entrar no arquivo de cabeçalho?
Que funções não deveriam?
Respostas:
O que colocar nos cabeçalhos:
#include
diretivas necessárias para tornar o cabeçalho compilável quando o cabeçalho é incluído em algum arquivo de origem.O que não pertence a um cabeçalho:
#include
Diretivas gratuitas . Essas inclusões gratuitas causam recompilação de coisas que não precisam ser recompiladas e às vezes podem fazer com que o sistema não seja 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.#include
, que estão sujeitas a alterações ou que são grandes demais. Essas funções em linha devem ter pouca ou nenhuma ventilação e, se houver, devem ser localizadas nos itens definidos 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 de 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 futuras são preferidas.
Há um lugar para uma
#include
diretiva gratuita , e isso é em um teste automatizado. Para cada arquivo de cabeçalho em um pacote de software, eu automaticamente giro e compilo o seguinte:A compilação deve estar limpa (ou seja, livre de avisos ou erros). Avisos ou erros relacionados a tipos incompletos ou desconhecidos significam que o arquivo de cabeçalho em teste tem algumas
#include
diretivas ausentes e / ou declarações avançadas. Observe bem: Só porque o teste passa não significa que o conjunto de#include
diretivas seja suficiente, muito menos o mínimo.fonte
Além do que já foi dito.
Os arquivos H devem sempre conter:
Os arquivos H nunca devem conter:
static
.(Eu também diria que nunca há motivo para usar variáveis globais / externas não constantes, em qualquer lugar, mas isso é uma discussão para outro post.)
fonte
Eu provavelmente nunca diria nunca, mas as instruções que geram dados e código à 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 quando são usados. Esses itens geralmente precisam ser usados em mais de um .c ou .cpp, para que pertençam ao .h.
Na minha opinião, um arquivo de cabeçalho deve ter a interface prática mínima para um correspondente .c ou .cpp. A interface pode incluir #defines, classe, typedef, definições de estrutura, protótipos de função e definições externas menos preferidas para variáveis globais. No entanto, se uma declaração for usada em apenas um arquivo de origem, provavelmente ela deve ser excluída do arquivo .he deve 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 capazes de compilar. Em alguns casos, pode haver muitos arquivos, portanto, temos alguns métodos eficazes para reduzir dependências externas, como declarações de encaminhamento para classes, que permitem usar ponteiros para objetos de uma classe sem incluir o que poderia ser uma grande árvore de arquivos de inclusão.
fonte
O arquivo de cabeçalho deve ter a seguinte organização:
Os arquivos de cabeçalho nunca devem conter definições de objeto, apenas definições de tipo e declarações de objeto.
fonte
Instruções que geram dados e código à medida que são analisadas, não devem estar em um
.h
arquivo. 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
.fonte