O que fazer se eu odeio arquivos de cabeçalho C ++?

25

Eu sempre fiquei confuso sobre os arquivos de cabeçalho. Eles são tão estranhos: você inclui o arquivo .h que não inclui o .cpp, mas o .cpp também é de alguma forma compilado.

Recentemente, ingressei em um projeto de equipe e, é claro, são usados ​​.h e .cpp.
Entendo que isso é muito importante, mas não posso conviver com copiar e colar todas as declarações de funções em cada uma das várias classes que temos.

Como lidar com a convenção de 2 arquivos com eficiência?
Existem ferramentas para ajudá-lo ou alterar automaticamente um arquivo que se parece com o exemplo abaixo para .h e .cpp? (especificamente para MS VC ++ 2010)

class A
{
...
    Type f(Type a,Type b)
    {
        //implementation here, not in another file!
    }
...
};

Type f(Type a)
{
     //implementation here
}
...
Oleh Prypin
fonte
8
Essa pergunta pode ser de várias maneiras. "Por que precisamos de cabeçalhos ao usar c ++" ou "Você acha que uma linguagem moderna que deve ser compilada deveria estar usando cabeçalhos?" Como é, tem 'O que faço "e" odeio "no título, o que desencadeia uma infinidade de bandeiras.
Tim Post
4
Sua pergunta faz parecer que você não entende C ++ ou como o sistema que você usa o compila. Aprenda a usá-lo corretamente e faça mais perguntas subjetivas.
David Thornley
31
Sua primeira frase indica que você "não entende tudo sobre os cabeçalhos". A inclusão de um arquivo .h não faz com que o arquivo .cpp correspondente seja "compilado de alguma forma também". Você compila arquivos .cpp de maneira independente. Se você não compilou o .cpp correspondente, a inclusão de um cabeçalho sem um arquivo de objeto correspondente fará com que o vinculador falhe.
Paul Butcher
5
O que fazer? Encontre outro idioma se isso incomoda muito.
Paul Nathan
5
Sobre o "não é possível viver com copiar e colar": sempre que alguém atualiza uma função, é necessário atualizar todos os locais onde é chamado de qualquer maneira. Como os chamadores são muito mais difíceis de encontrar do que a declaração no arquivo de cabeçalho, a atualização do cabeçalho é apenas um detalhe menor.
Sjoerd

Respostas:

15

Escrevendo C ++ mais amigável à refatoração

No C ++, você não precisa usar cabeçalhos. Você pode definir o objeto inteiro em um arquivo, exatamente como faria com C # ou Java. Geralmente, os desenvolvedores de C mantêm chamadas externas em um arquivo de cabeçalho. Todas as chamadas internas seriam definidas no arquivo .c. Da mesma forma, você pode reservar seus arquivos .h em C ++ para as classes / interfaces (classes abstratas virtuais puras) / etc. que devem ser compartilhados fora da DLL. Para classes / estruturas / interfaces internas, etc., você simplesmente incluiria o arquivo .cpp necessário:

#include<myclass.cpp>

Essa não parece ser a abordagem mais popular, mas é legal em C ++. Definitivamente, seria uma possibilidade para todo o seu código interno. Isso permite que o código interno e o conjunto de classes mudem muito mais radicalmente, fornecendo uma interface mais estável para o código fora da sua biblioteca / executável interagir.

Ter toda a sua classe dentro de um arquivo facilitará o que você deseja. Ele não resolverá o problema de renomear um método e ter que procurar em todos os lugares em que esse método é chamado, mas garantirá que você tenha mensagens de erro mais inteligíveis. Nada pior do que o cabeçalho declarar um método de uma maneira, mas você o implementa de maneira diferente. Outro código que chama o arquivo de cabeçalho será compilado corretamente e você receberá uma exceção de link, enquanto o arquivo de implementação será o que reclama que o método não foi definido. Quando você define todos os métodos em vigor (na declaração de classe real), recebe a mesma mensagem de erro, independentemente do arquivo que o inclui.

Você também pode querer analisar esta pergunta: Boas ferramentas de refatoração para C ++

Como o C / C ++ resolve arquivos de cabeçalho / implementação

No nível C base (e o C ++ é construído sobre essa base), os arquivos de cabeçalho declaram a promessa de uma função / estrutura / variável que é suficiente para permitir que um compilador crie o arquivo de objeto. Da mesma forma, os arquivos de cabeçalho C ++ declaram a promessa de funções, estruturas, classes, etc. É essa definição que o compilador usa para reservar espaço na pilha, etc.

Os arquivos .c ou .cpp têm a implementação. Como o compilador converte cada arquivo de implementação em um objeto, há ganchos para conceitos não implementados (o que foi declarado no cabeçalho). O vinculador vincula os ganchos às implementações em outros arquivos de objeto e cria um binário maior que inclui todo o código (biblioteca compartilhada ou executável).

VS Specific

Quanto ao trabalho com aqueles no Visual Studio, existem alguns assistentes que ajudam a tornar as coisas um pouco mais fáceis. O novo assistente de classe criará seu par correspondente de cabeçalho e arquivos de implementação. Existe até um recurso de navegador de classe que permitirá que você declare novos métodos. Ele injeta a definição no cabeçalho e o stub de implementação no arquivo .cpp. O Visual Studio possui esses recursos há mais de uma década (desde que eu os usei).

Berin Loritsch
fonte
O problema é que estou fortemente modificar as classes o tempo todo, e não apenas a adição de novas funções, etc
Oleh Prypin
5
@BlaXpirit: Então, por que você está modificando bastante as aulas o tempo todo? Uma das idéias por trás do design do OO é ter muitos blocos de construção razoavelmente estáveis. Se eu estivesse modificando muito as classes, gostaria de uma linguagem mais dinâmica, como Common Lisp ou Python.
David Thornley
2
É isso que estou fazendo. Estou melhorando / modificar os "blocos de construção" e adicionando novos
Oleh Prypin
C ++ nunca foi refatorador amigável. O conceito de refatoração não ganhou impulso até que houvesse ferramentas que facilitassem a execução nos IDEs Java. NOTA: esses recursos estavam disponíveis para desenvolvedores do Smalltalk e outros idiomas, mas não se tornaram populares até estarem disponíveis para muitas pessoas. Até agora, ainda não vi alguém implementando isso de forma inteligente em C ++. Talvez o Resharper do JetBrains? Eu sei que ele faz código C # e VB, mas não tenho certeza se isso lhe dará refatoração em C ++.
Berin Loritsch
@ Berin: Procurei ferramentas de refatoração C ++ há um ou dois anos e encontrei duas coisas. Eles eram bastante caros na época, e eu não vi versões de teste, então não sei o que eles fizeram. Além disso, trabalhava apenas com o emacs, o que limitaria sua eficácia em uma loja do Visual Studio.
David Thornley
13

Torne-se um desenvolvedor Java.

Se você realmente precisa continuar desenvolvendo em C ++, pode tentar usar um IDE. Geralmente, eles oferecem algum mecanismo pelo qual você pode adicionar um método a uma classe e coloca automaticamente a declaração no arquivo .h e a definição no arquivo .cpp.

Paul Butcher
fonte
2
kthx, conheço um pouco o Java, mas você não pode criar DLLs Win32 de baixo nível com ele, pode?
precisa saber é o seguinte
41
Não sei por que, mas 'Torne-se um desenvolvedor Java' de alguma forma parece um insulto: D.
Oliver Weiler
2
Se você quer fazer um nível baixo, esqueça tudo sobre 'idiomas fáceis'. Custos baixos, suor e lágrimas.
Batibix
5
Não é uma resposta particularmente útil.
ChrisF
1
@ OliverWeiler Eu não percebo "me tornar um desenvolvedor Java" como um insulto. Eu programa tanto em C ++ quanto em Java, mas minha preferência é de longe o Java, porque é muito mais fácil sentar e distribuir o código que funciona (e mais portátil). Se, por algum motivo, detestar a existência de arquivos de cabeçalho, tentar Java pode ser a escolha certa (embora seja estranho que você odeie arquivos de cabeçalho; eu consideraria uma alteração no IDE).
Trixie Wolf
7

Você poderia estar interessado no makeheaders programa a partir Hwaci (aqueles que fazem SQLite e Fossil).

Veja também como o fóssil é construído para ter uma ideia.

Benoit
fonte
5
O solicitante ainda precisa entender muito bem a relação entre .h e .cpp.
Job
2
Eu entendo o básico. A resposta parece ser exatamente o que eu preciso.
precisa saber é o seguinte
4

Quando você escreve as primeiras linhas de uma nova turma, geralmente é porque você precisa dela em um só lugar naquele momento. Posteriormente, pode ser usado em mais locais, mas inicialmente não é.

Muitas das minhas aulas começam no topo do arquivo .cpp atual. Quando ele é estabilizado o suficiente para usá-lo em vários locais, colo-o em um cabeçalho. Embora muitas vezes a classe desapareça tão rápido quanto parecia.

Sjoerd
fonte
-1

Como sugestão para ajudar a lidar com arquivos de cabeçalho C ++, é comum usá-los sem extensão ou sufixo, como as bibliotecas "GCC".

Se esse for o seu caso, sugiro usar uma extensão ou sufixo de arquivo " .hpp" (ou desactivar " .hxx").

Pode ser necessário configurar o compilador, o ambiente do desenvolvedor ou o programa Built.

umlcat
fonte
3
Você está falando sobre como incluir um arquivo como esse #include <iostream>? Aqueles não são apenas para a biblioteca do GCC. De fato, é definido no padrão C ++ de 1997 , seção 17.3.1.2. Eu evitaria nomear arquivos assim. Você pode, mas a razão pela qual a biblioteca padrão C ++ fez isso foi provavelmente para evitar conflitos de nomeação. Na verdade, acho muito estranho quando os compiladores adicionam automaticamente um '.h' quando você inclui um cabeçalho, isso me parece bastante incomum. E eu nunca vi ninguém nomear cabeçalhos sem sufixo, exceto a biblioteca padrão c ++.
precisa saber é o seguinte
1
Além disso, devo observar que todos os compiladores que usei, exceto o borland (que eu odeio muito), não adicionam automaticamente um '.h' ou '.hpp' ou '.hxx' quando você tenta para incluir um arquivo sem sufixo. Não espere #include <someclass>ser lido como #include <someclass.hpp>em todos os compiladores. Seu código irá quebrar.
vedosity