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 #included 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.hrealmente depender, <map>mas em todos os lugares em que foi usado nos .ccarquivos <map>já estiver incluído, provavelmente não perceberemos. Até que alguém tentou incluir foo.hsem antes incluir <map>. E então eles ficariam irritados.
.htem pelo menos um .cppque 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 #includes 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 #included 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.cppdeve incluir source1.hantes 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.hantes de mais nada.
Raciocínio: a inclusão de source1.houtros arquivos anteriores antes garante que ele possa permanecer sozinho sem dependências. Se source1.hassumir 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 #includediretrizes 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 offsetofem 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 offsetofem stddef.h indicará um erro de redefinição de macro.
Oramos para não encontrar mais nenhum desses casos em nossa carreira.