Pourquoi la déclaration directe est nécessaire en C ++
Le compilateur veut s'assurer que vous n'avez pas fait d'erreurs d'orthographe ou passé le mauvais nombre d'arguments à la fonction. Ainsi, il insiste sur le fait qu'il voit d'abord une déclaration «add» (ou tout autre type, classe ou fonction) avant d'être utilisé.
Cela permet simplement au compilateur de faire un meilleur travail de validation du code, et lui permet de ranger les extrémités lâches afin qu'il puisse produire un fichier objet soigné. Si vous n'aviez pas à transmettre de déclaration, le compilateur produirait un fichier objet qui devrait contenir des informations sur toutes les suppositions possibles quant à ce que la fonction «ajouter» pourrait être. Et l'éditeur de liens devrait contenir une logique très intelligente pour essayer de déterminer quel «ajout» vous aviez réellement l'intention d'appeler, lorsque la fonction «ajouter» peut vivre dans un fichier objet différent que l'éditeur de liens joint à celui qui utilise ajouter pour produire une DLL ou un exe. Il est possible que l'éditeur de liens obtienne le mauvais ajout. Supposons que vous vouliez utiliser int add (int a, float b), mais que vous avez accidentellement oublié de l'écrire, mais l'éditeur de liens a trouvé un int add déjà existant (int a, int b) et a pensé que c'était le bon et l'a utilisé à la place. Votre code compilerait, mais ne ferait pas ce que vous attendiez.
Donc, juste pour garder les choses explicites et éviter les suppositions, etc., le compilateur insiste pour que vous déclariez tout avant qu'il ne soit utilisé.
Différence entre déclaration et définition
En passant, il est important de connaître la différence entre une déclaration et une définition. Une déclaration donne juste assez de code pour montrer à quoi ressemble quelque chose, donc pour une fonction, c'est le type de retour, la convention d'appel, le nom de la méthode, les arguments et leurs types. Mais le code de la méthode n'est pas requis. Pour une définition, vous avez également besoin de la déclaration et du code de la fonction.
Comment les déclarations prévisionnelles peuvent réduire considérablement les temps de génération
Vous pouvez obtenir la déclaration d'une fonction dans votre fichier .cpp ou .h actuel en # incluant l'en-tête qui contient déjà une déclaration de la fonction. Cependant, cela peut ralentir votre compilation, surtout si vous # incluez un en-tête dans un .h au lieu de .cpp de votre programme, car tout ce qui #inclut le .h que vous écrivez finirait par # inclure tous les en-têtes vous avez également écrit #includes pour. Du coup, le compilateur a #inclus des pages et des pages de code dont il a besoin pour compiler même lorsque vous ne souhaitez utiliser qu'une ou deux fonctions. Pour éviter cela, vous pouvez utiliser une déclaration directe et tapez simplement la déclaration de la fonction vous-même en haut du fichier. Si vous n'utilisez que quelques fonctions, cela peut vraiment rendre vos compilations plus rapides que de toujours inclure # l'en-tête. Pour les très gros projets,
Briser les références cycliques où deux définitions utilisent les deux
De plus, les déclarations à terme peuvent vous aider à rompre les cycles. C'est là que deux fonctions essaient toutes deux de s'utiliser. Lorsque cela se produit (et c'est une chose parfaitement valable à faire), vous pouvez #inclure un fichier d'en-tête, mais ce fichier d'en-tête essaie de #inclure le fichier d'en-tête que vous écrivez actuellement .... qui #inclut ensuite l'autre en-tête , qui #inclut celui que vous écrivez. Vous êtes coincé dans une situation de poulet et d'oeuf avec chaque fichier d'en-tête essayant de ré-inclure l'autre. Pour résoudre ce problème, vous pouvez déclarer les pièces dont vous avez besoin dans l'un des fichiers et laisser le #include hors de ce fichier.
Par exemple:
Fichier Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
File Wheel.h
Hmm ... la déclaration de Car est requise ici car Wheel a un pointeur sur Car, mais Car.h ne peut pas être inclus ici car cela entraînerait une erreur de compilation. Si Car.h était inclus, cela essaierait alors d'inclure Wheel.h qui inclurait Car.h qui inclurait Wheel.h et cela continuerait pour toujours, donc à la place le compilateur soulève une erreur. La solution est de transmettre à la place déclarer Car:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Si la classe Wheel avait des méthodes qui doivent appeler des méthodes de car, ces méthodes pourraient être définies dans Wheel.cpp et Wheel.cpp est maintenant capable d'inclure Car.h sans provoquer de cycle.