Que ordem deve incluir os arquivos a serem especificados, ou seja, quais são os motivos para incluir um cabeçalho antes do outro?
Por exemplo, os arquivos do sistema, STL e Boost vão antes ou depois do local incluir arquivos?
Que ordem deve incluir os arquivos a serem especificados, ou seja, quais são os motivos para incluir um cabeçalho antes do outro?
Por exemplo, os arquivos do sistema, STL e Boost vão antes ou depois do local incluir arquivos?
Respostas:
Acho que não há um pedido recomendado, desde que seja compilado! O que é irritante é quando alguns cabeçalhos exigem que outros sejam incluídos primeiro ... Esse é um problema com os próprios cabeçalhos, não com a ordem de inclusões.
Minha preferência pessoal é ir do local para o global, cada subseção em ordem alfabética, ou seja:
Minha justificativa para 1. é que ele deve provar que cada cabeçalho (para o qual existe um cpp) pode ser #include
d sem pré-requisitos (terminus technicus: o cabeçalho é "independente"). E o resto parece fluir logicamente a partir daí.
O importante é ter em mente que seus cabeçalhos não devem depender de outros cabeçalhos serem incluídos primeiro. Uma maneira de garantir isso é incluir seus cabeçalhos antes de qualquer outro cabeçalho.
"Thinking in C ++" em particular menciona isso, referenciando o "Large Scale C ++ Software Design" da Lakos:
Erros de uso latente podem ser evitados, garantindo que o arquivo .h de um componente seja analisado por si só - sem declarações ou definições fornecidas externamente ... Incluindo o arquivo .h como a primeira linha do arquivo .c garante que nenhuma parte crítica Faltam informações intrínsecas à interface física do componente no arquivo .h (ou, se houver, você as descobrirá assim que tentar compilar o arquivo .c).
Ou seja, inclua na seguinte ordem:
Se algum dos cabeçalhos tiver um problema ao ser incluído nesta ordem, corrija-os (se o seu) ou não os use. Boicote bibliotecas que não escrevem cabeçalhos limpos.
O guia de estilo C ++ do Google argumenta quase ao contrário, sem realmente nenhuma justificativa; Pessoalmente, sou a favor da abordagem de Lakos.
Sigo duas regras simples que evitam a grande maioria dos problemas:
Eu também sigo as diretrizes de:
Em outras palavras:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
Embora, sendo diretrizes, isso seja subjetivo. As regras, por outro lado, imponho rigidamente, até o ponto de fornecer arquivos de cabeçalho 'wrapper' com guardas de inclusão e inclusões agrupadas, se algum desenvolvedor detestável de terceiros não assinar a minha visão :-)
Para adicionar meu próprio tijolo à parede.
Então eu costumo ir assim:
// myproject/src/example.cpp
#include "myproject/example.h"
#include <algorithm>
#include <set>
#include <vector>
#include <3rdparty/foo.h>
#include <3rdparty/bar.h>
#include "myproject/another.h"
#include "myproject/specific/bla.h"
#include "detail/impl.h"
Cada grupo é separado por uma linha em branco da próxima:
Observe também que, além dos cabeçalhos do sistema, cada arquivo está em uma pasta com o nome de seu espaço para nome, apenas porque é mais fácil rastreá-los dessa maneira.
#define
é que estragar outro código) e para prevenir dependências implícitas. Por exemplo, se nosso arquivo de cabeçalho da base de código foo.h
realmente depender, <map>
mas em todos os lugares em que foi usado nos .cc
arquivos <map>
já estiver incluído, provavelmente não perceberemos. Até que alguém tentou incluir foo.h
sem antes incluir <map>
. E então eles ficariam irritados.
.h
tem pelo menos um .cpp
que o inclui primeiro (de fato, no meu código pessoal, o teste de unidade associado o inclui primeiro e o código fonte o inclui em seu grupo legítimo ) Não em relação a ser influenciado, se qualquer um dos cabeçalhos inclui <map>
, em seguida, todos os cabeçalhos incluídos posteriormente são influenciados de qualquer maneira, por isso parece uma batalha perdida para mim.
Header corresponding to this cpp file first (sanity check)
. Existe algo em particular se #include "myproject/example.h"
for movido para o final de todas as inclusões?
Eu recomendo:
E, claro, ordem alfabética em cada seção, sempre que possível.
Sempre use declarações avançadas para evitar #include
s desnecessários nos arquivos de cabeçalho.
Tenho certeza de que essa não é uma prática recomendada em nenhum lugar do mundo, mas eu gosto de alinhar o sistema por tamanho do nome do arquivo, classificado lexicamente no mesmo comprimento. Igual a:
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
Eu acho que é uma boa ideia incluir seus próprios cabeçalhos antes de outros povos, para evitar a vergonha da dependência da ordem de inclusão.
windows.h
.
Isto não é subjetivo. Verifique se os cabeçalhos não confiam em ser #include
d em ordem específica. Você pode ter certeza de que não importa em que ordem você inclui os cabeçalhos STL ou Boost.
Primeiro, inclua o cabeçalho correspondente ao .cpp ... em outras palavras, source1.cpp
deve incluir source1.h
antes de incluir qualquer outra coisa. A única exceção em que consigo pensar é ao usar o MSVC com cabeçalhos pré-compilados; nesse caso, você é forçado a incluir stdafx.h
antes de mais nada.
Raciocínio: a inclusão de source1.h
outros arquivos anteriores antes garante que ele possa permanecer sozinho sem dependências. Se source1.h
assumir uma dependência em uma data posterior, o compilador o alertará imediatamente para adicionar as declarações de encaminhamento necessárias source1.h
. Por sua vez, isso garante que os cabeçalhos possam ser incluídos em qualquer ordem por seus dependentes.
Exemplo:
source1.h
class Class1 {
Class2 c2; // a dependency which has not been forward declared
};
source1.cpp
#include "source1.h" // now compiler will alert you saying that Class2 is undefined
// so you can forward declare Class2 within source1.h
...
Usuários de MSVC: eu recomendo o uso de cabeçalhos pré-compilados. Portanto, mova todas as #include
diretrizes para cabeçalhos padrão (e outros que nunca serão alterados) para stdafx.h
.
Inclua do mais específico ao menos específico, começando com o .hpp correspondente para o .cpp, se houver. Dessa forma, quaisquer dependências ocultas nos arquivos de cabeçalho que não sejam auto-suficientes serão reveladas.
Isso é complicado pelo uso de cabeçalhos pré-compilados. Uma maneira de contornar isso é, sem especificar o compilador do seu projeto, é usar um dos cabeçalhos do projeto como arquivo de inclusão do cabeçalho pré-compilado.
É uma pergunta difícil no mundo C / C ++, com tantos elementos além do padrão.
Acho que a ordem dos arquivos de cabeçalho não é um problema sério, desde que seja compilado, como o squelart disse.
Minhas idéias são: se não houver conflito de símbolos em todos esses cabeçalhos, qualquer ordem será válida e o problema de dependência do cabeçalho poderá ser corrigido posteriormente, adicionando #include lines ao .h defeituoso.
O verdadeiro aborrecimento surge quando algum cabeçalho altera sua ação (verificando #if condições) de acordo com o que os cabeçalhos estão acima.
Por exemplo, em stddef.h no VS2005, há:
#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Agora o problema: se eu tiver um cabeçalho personalizado ("custom.h") que precise ser usado com muitos compiladores, incluindo alguns mais antigos que não fornecem offsetof
em seus cabeçalhos de sistema, devo escrever no meu cabeçalho:
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
E não se esqueça de informar ao usuário que #include "custom.h"
após todos os cabeçalhos do sistema, caso contrário, a linha de offsetof
em stddef.h indicará um erro de redefinição de macro.
Oramos para não encontrar mais nenhum desses casos em nossa carreira.