Primeiro, para responder à sua primeira consulta:
Quando você vê isso no arquivo .h :
#ifndef FILE_H
#define FILE_H
/* ... Declarations etc here ... */
#endif
Essa é uma técnica de pré-processador para impedir que um arquivo de cabeçalho seja incluído várias vezes, o que pode ser problemático por vários motivos. Durante a compilação do seu projeto, cada arquivo .cpp (geralmente) é compilado. Em termos simples, isso significa que o compilador pegará seu arquivo .cpp , abrirá todos os arquivos #included
, concatenará todos eles em um arquivo de texto maciço, executará uma análise de sintaxe e, finalmente, o converterá em código intermediário, otimizará / executará outros tarefas e, finalmente, gere a saída do assembly para a arquitetura de destino. Por esse motivo, se um arquivo estiver #included
várias vezes sob um .cpparquivo, o compilador anexará o conteúdo do arquivo duas vezes; portanto, se houver definições nesse arquivo, você receberá um erro do compilador informando que redefiniu uma variável. Quando o arquivo é processado pela etapa do pré-processador no processo de compilação, na primeira vez em que seu conteúdo é atingido, as duas primeiras linhas verificam se FILE_H
foi definido para o pré-processador. Caso contrário, ele definirá a diretiva. Na próxima vez que o conteúdo do arquivo for visto pelo pré-processador, a verificação será falsa e, portanto, será varrida imediatamente para o diretórioFILE_H
e continuará processando o código entre ele e a e continuado depois dele. Isso evita erros de redefinição.#endif
FILE_H
#endif
E para resolver sua segunda preocupação:
Na programação C ++, como prática geral, separamos o desenvolvimento em dois tipos de arquivo. Uma é com uma extensão .he chamamos isso de "arquivo de cabeçalho". Eles geralmente fornecem uma declaração de funções, classes, estruturas, variáveis globais, typedefs, macros e definições de pré-processamento, etc. Basicamente, eles apenas fornecem informações sobre seu código. Então temos a extensão .cpp que chamamos de "arquivo de código". Isso fornecerá definições para essas funções, membros da classe, quaisquer membros da estrutura que precisem de definições, variáveis globais, etc. Portanto, o arquivo .h declara código e o .cpp arquivo implementa essa declaração. Por esse motivo, geralmente durante a compilação compilamos cada .cpparquivo em um objeto e, em seguida, vincule esses objetos (porque você quase nunca vê um arquivo .cpp incluir outro arquivo .cpp ).
Como esses externos são resolvidos é um trabalho para o vinculador. Quando seu compilador processa main.cpp , ele obtém declarações para o código em class.cpp incluindo class.h . Ele só precisa saber como são essas funções ou variáveis (que é o que uma declaração fornece). Portanto, ele compila seu arquivo main.cpp em algum arquivo de objeto (chame-o de main.obj ). Da mesma forma, class.cpp é compilado em um class.objArquivo. Para produzir o executável final, um vinculador é chamado para vincular esses dois arquivos de objeto. Para quaisquer variáveis ou funções externas não resolvidas, o compilador colocará um esboço onde o acesso acontece. O vinculador pegará esse stub e procurará o código ou a variável em outro arquivo de objeto listado e, se encontrado, combina o código dos dois arquivos de objeto em um arquivo de saída e substitui o stub pelo local final da função ou variável. Dessa forma, seu código em main.cpp pode chamar funções e usar variáveis em class.cpp SE E SOMENTE SE ELES SÃO DECLARADOS EM class.h .
Eu espero que isso tenha sido útil.