Por que a declaração direta é necessária em C ++
O compilador deseja garantir que você não tenha cometido erros de ortografia ou passado o número errado de argumentos para a função. Portanto, ele insiste em ver primeiro uma declaração de 'add' (ou quaisquer outros tipos, classes ou funções) antes de ser usada.
Isso realmente permite que o compilador faça um trabalho melhor de validação do código e permite que ele solte pontas soltas para que possa produzir um arquivo de objeto com aparência elegante. Se você não tivesse que encaminhar declarar as coisas, o compilador produziria um arquivo de objeto que teria que conter informações sobre todas as suposições possíveis sobre qual poderia ser a função 'adicionar'. E o vinculador precisaria conter uma lógica muito inteligente para tentar descobrir qual 'add' você realmente pretendia chamar, quando a função 'add' pode viver em um arquivo de objeto diferente que o vinculador está se unindo ao que usa add para produzir uma DLL ou EXE. É possível que o vinculador receba a adição errada. Digamos que você queira usar int add (int a, float b), mas acidentalmente esqueceu de escrevê-lo, mas o vinculador encontrou um int add já existente (int a, int b) e achou que era o correto e usou isso em seu lugar. Seu código seria compilado, mas não faria o que você esperava.
Portanto, apenas para manter as coisas explícitas e evitar adivinhações, etc, o compilador insiste em que você declare tudo antes de usá-lo.
Diferença entre declaração e definição
Como um aparte, é importante saber a diferença entre uma declaração e uma definição. Uma declaração apenas fornece código suficiente para mostrar como algo se parece; portanto, para uma função, esse é o tipo de retorno, convenção de chamada, nome do método, argumentos e seus tipos. Mas o código para o método não é necessário. Para uma definição, você precisa da declaração e também do código para a função.
Como declarações futuras podem reduzir significativamente os tempos de construção
Você pode obter a declaração de uma função no seu arquivo .cpp ou .h atual # incluindo o cabeçalho que já contém uma declaração da função. No entanto, isso pode atrasar sua compilação, especialmente se você # incluir um cabeçalho em .h em vez de .cpp do seu programa, pois tudo o que #inclui o .h que você está escrevendo acabará # incluindo todos os cabeçalhos você escreveu #includes for also. De repente, o compilador inclui # páginas e páginas de código que ele precisa compilar, mesmo quando você só queria usar uma ou duas funções. Para evitar isso, você pode usar uma declaração direta e apenas digitar a declaração da função na parte superior do arquivo. Se você estiver usando apenas algumas funções, isso pode realmente tornar suas compilações mais rápidas em comparação a sempre #incluindo o cabeçalho. Para projetos realmente grandes,
Quebrar referências cíclicas em que duas definições se usam
Além disso, as declarações avançadas podem ajudá-lo a interromper os ciclos. É aqui que duas funções tentam se usar. Quando isso acontece (e é uma coisa perfeitamente válida a ser feita), você pode # incluir um arquivo de cabeçalho, mas esse arquivo de cabeçalho tenta # incluir o arquivo de cabeçalho que você está escrevendo atualmente .... que, em seguida, inclui o outro cabeçalho , que # inclui o que você está escrevendo. Você está preso em uma situação de galinha e ovo, com cada arquivo de cabeçalho tentando # incluir o outro. Para resolver isso, você pode encaminhar novamente as partes necessárias em um dos arquivos e deixar o #include fora desse arquivo.
Por exemplo:
Arquivo Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
Arquivo Wheel.h
Hmm ... a declaração de Car é necessária aqui, pois Wheel tem um ponteiro para um Car, mas Car.h não pode ser incluído aqui, pois resultaria em um erro do compilador. Se Car.h fosse incluído, isso tentaria incluir Wheel.h, que incluiria Car.h, que incluiria Wheel.he isso continuaria para sempre, portanto, o compilador gera um erro. A solução é encaminhar declarar Car em vez disso:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Se a classe Wheel tiver métodos que precisam chamar métodos de carro, esses métodos poderão ser definidos em Wheel.cpp e Wheel.cpp agora poderá incluir Car.h sem causar um ciclo.