Pergunta

O que ordem deve cabeçalhos ser declarado em um arquivo de cabeçalho / CPP? Obviamente, aqueles que são obrigados por cabeçalhos subsequentes devem ser anterior e cabeçalhos de classe específicos devem estar no escopo CPP escopo não cabeçalho, mas existe a / melhor prática convenção ordem set?

Foi útil?

Solução

Em um arquivo de cabeçalho você tem que incluir todos os cabeçalhos para torná-lo compilable. E não se esqueça de usar declarações para a frente em vez de alguns cabeçalhos.

Em um arquivo de origem:

  • arquivo de cabeçalho correspondido
  • necessárias cabeçalhos projeto
  • 3rd party bibliotecas cabeçalhos
  • bibliotecas padrão cabeçalhos
  • cabeçalhos do sistema

Em que ordem você não perca nenhum dos seus arquivos de cabeçalho que se esqueceu de incluir bibliotecas por conta própria.

Outras dicas

Boas práticas: cada arquivo .h deve ter um .cpp que inclui que .h primeiro antes de qualquer outra coisa. Isto prova que qualquer arquivo .h podem ser colocados em primeiro lugar.

Mesmo se o cabeçalho não requer implementação, você faz um .cpp que inclui apenas o arquivo .h e nada mais.

Isto significa então que você pode responder a sua pergunta qualquer jeito que você gosta. Não importa que ordem você incluí-los em.

Para mais ótimas dicas, tente este livro: Large-Scale C ++ Software Design - é uma vergonha que é tão caro, mas é praticamente um guia de sobrevivência para o layout do código-fonte C ++

.

Em arquivos de cabeçalho, que tendem a colocar cabeçalhos padrão primeiro, depois os meus próprios cabeçalhos (ambas as listas sendo ordenados alfabeticamente). Em arquivos de implementação, coloco primeiro o cabeçalho correspondente (se houver), então cabeçalhos padrões e outros cabeçalhos de dependência.

A ordem é de pouca importância, exceto se você faz um grande uso de macros e #define; nesse caso, você deve verificar que a macro que você definiu não substitui a anteriormente incluído um (exceto se é isso que você quer, é claro).

No que se refere esta declaração

aqueles que são obrigados por cabeçalhos subsequentes devem ser anterior

Um cabeçalho não deve confiar em outros cabeçalhos ser incluído antes! Se ele requer cabeçalhos, ele só inclui-los. guardas de cabeçalho irá impedir a inclusão múltipla:

#ifndef FOO_HEADER_H
#define FOO_HEADER_H
...
#endif

Editar

Desde que eu escrevi essa resposta, eu mudei minha maneira de ordenar a incluir directivas no meu código. Agora, eu tento cabeçalhos sempre colocar em ordem de padronização crescente, para que os cabeçalhos do meu projeto a chegar primeiro, seguido pelo 3º cabeçalhos bibliotecas partido, seguido de cabeçalhos padrão.

Por exemplo, se um de meu arquivo usa uma biblioteca que eu escrevi, Qt, Boost e da biblioteca padrão, vou pedir o inclui os seguintes:

//foo.cpp
#include "foo.hpp"

#include <my_library.hpp>
// other headers related to my_library

#include <QtCore/qalgorithms.h>
// other Qt headers

#include <boost/format.hpp> // Boost is arguably more standard than Qt
// other boost headers

#include <algorithms>
// other standard algorithms

A razão pela qual eu faço isso é detectar dependências que estão faltando em meus próprios cabeçalhos: vamos supor, por exemplo, que os usos my_library.hpp std::copy, mas não inclui <algorithm>. Se eu incluí-lo após <algorithm> em foo.cpp, essa dependência faltando vai passar despercebida. Pelo contrário, com o fim Eu apenas apresentado, o compilador vai reclamar que std::copy não foi declarado, permitindo-me my_library.hpp correta.

Em cada grupo "biblioteca", eu tento manter a incluir diretivas em ordem alfabética, para encontrá-los com mais facilidade.

Em uma nota, uma boa prática também é limitar a um máximo a dependência entre arquivos de cabeçalho. Os arquivos devem incluir como pequenos cabeçalhos quanto possível, especialmente os cabeçalhos dos arquivos. De fato, os mais cabeçalhos que incluem, mais código precisa ser recompilados quando algo muda. Uma boa maneira de limitar essas dependências é usar a declaração para a frente, que é muitas vezes suficiente em arquivos de cabeçalho (ver Quando posso usar uma declaração para a frente ? ).

Guia de Estilo Google C ++, nomes ea ordem de Inclui :

Em dir / foo.cc, cujo principal objetivo é implementar ou testar o material em dir2 / foo2.h, encomendar o seu inclui o seguinte:

  • dir2 / foo2.h (local preferido - ver detalhes abaixo).
  • arquivos de sistema C.
  • arquivos de sistema C ++.
  • .h Outras das bibliotecas.
  • .h do seu projeto.

Eu costumava encomendá-los em ordem alfabética (mais fácil de encontrar)

O "como" não é óbvia, mas "o que" é. Seu objetivo é ter certeza de que a ordem em que você incluir arquivos de cabeçalho não importa (e eu digo "NUNCA!").

Uma boa ajuda é para testar se os arquivos de cabeçalho compilar quando a construção de arquivos CPP (um para cada arquivo de cabeçalho), que incluem apenas um deles.

Para arquivos .cpp, você deve incluir o cabeçalho da classe ou o que você está implementando em primeiro lugar, para que você pegar o caso em que este cabeçalho está faltando alguma inclui. Depois disso, as orientações de codificação mais tendem a incluem cabeçalhos, cabeçalhos de sistema primeiros projectos segundo, por exemplo, o Guia de Estilo Google C ++ .

É uma coisa dependência e que depende em grande parte o que você colocar em nossas cabeçalhos. A verdade é que você pode ser realmente notório sobre este e minimizar para manter seu inclui rigorosa, mas você eventualmente vai correr em um cenário onde você quer usar guardas de inclusão.

#ifndef MY_HEADER_H
#define MY_HEADER_H
//...
#endif

O problema não é que aparente no início, mas como a complexidade do software cresce assim que faz suas dependências. Você pode fazer bem, e ser esperto sobre isso, mas projetos maiores em C ++ são geralmente cheio de inclui. Você pode tentar, mas você só pode fazer muito. Então, ser diligente e pensar sobre o seu inclui, SIM! Mas você vai certamente ter dependências cíclicas em algum momento e é por isso que você precisa guardas de inclusão.

Se um cabeçalho precisa de outros cabeçalhos então ele só inclui-los nesse cabeçalho.

Tente estruturar seu código para você passar ponteiros ou referências e declarar frente onde você pode.

Na implementação, em seguida, o cabeçalho que define ele deve ser listado primeiro (exceto em Visual Studio se você estiver usando PCH então stdafx iria primeiro).

Eu geralmente listá-los como eu preciso.

Eu encontrei a seguinte convenção o mais útil:

module.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project

O importante é colocar o cabeçalho do módulo como o primeiro cabeçalho não pré-compilado. Isso garante "module.h" não tem dependências inesperadas.

Se você estiver trabalhando em um projeto grande, com tempos de acesso ao disco lento, eu vi esse estilo usado para diminuir o tempo de construção:

module.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project
#if !defined _OTHER_MODULE_GUARD_
#include "other_module.h"
#endif 

#if !defined _ANOTHER_MODULE_GUARD_
#include "another_module.h"
#endif 

É um pouco detalhado, mas não salva no disco buscando desde o cabeçalho não será procurado / aberto se ele já foi incluído. Sem a verificação de guarda, o compilador irá procurar e abrir o arquivo de cabeçalho, analisar o arquivo inteiro para acabar #ifdefing toda a fora do arquivo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top