Dois-je mettre les inclusions dans le fichier d'en-tête ou le fichier source? Si le fichier d'en-tête contient les instructions d'inclusion, alors si j'inclus ce fichier d'en-tête dans ma source, mon fichier source aura-t-il tous les fichiers inclus qui étaient dans mon en-tête? Ou devrais-je les inclure uniquement dans mon fichier source?
107
Réponses:
Ne mettez des inclus dans un en-tête que si l'en-tête lui-même en a besoin.
Exemples:
size_t
. Puis#include <stddef.h>
dans le fichier d' en- tête .strlen
. Puis#include <string.h>
dans le fichier source .la source
size_t
?size_t
oustd::string
?Il y a eu pas mal de désaccord à ce sujet au fil des ans. À un moment donné, il était traditionnel qu'un en-tête ne déclare que ce qui était dans le module auquel il était lié, tant d'en- têtes avaient des exigences spécifiques que vous
#include
un certain ensemble d'en-têtes (dans un ordre spécifique). Certains programmeurs C extrêmement traditionnels suivent encore ce modèle (religieusement, dans au moins certains cas).Plus récemment, il y a eu un mouvement pour rendre la plupart des en-têtes autonomes. Si cet en-tête nécessite autre chose, l'en-tête lui-même gère cela, en s'assurant que tout ce dont il a besoin est inclus (dans le bon ordre, s'il y a des problèmes de commande). Personnellement, je préfère cela - surtout lorsque l'ordre des en-têtes peut être important, cela résout le problème une fois, au lieu de demander à tous ceux qui l'utilisent de résoudre le problème une fois de plus.
Notez que la plupart des en-têtes ne doivent contenir que des déclarations. Cela signifie que l'ajout d'un en-tête inutile ne devrait (normalement) pas avoir d'effet sur votre exécutable final. Le pire qui arrive est que cela ralentit un peu la compilation.
la source
Vos
#include
s doivent être des fichiers d'en-tête, et chaque fichier (source ou en-tête) doit#include
contenir les fichiers d'en-tête dont il a besoin. Les fichiers d'en-tête doivent contenir#include
le minimum de fichiers d'en-tête nécessaire, et les fichiers source devraient également, bien que ce ne soit pas aussi important pour les fichiers source.Le fichier source aura les en-têtes qu'il
#include
s, et les en-têtes eux#include
, et ainsi de suite jusqu'à la profondeur d'imbrication maximale. C'est pourquoi vous ne voulez pas de#include
s superflus dans les fichiers d'en-tête: ils peuvent amener un fichier source à inclure beaucoup de fichiers d'en-tête dont il n'a peut-être pas besoin, ce qui ralentit la compilation.Cela signifie qu'il est tout à fait possible que les fichiers d'en-tête soient inclus deux fois, et cela peut être un problème. La méthode traditionnelle consiste à mettre «inclure les gardes» dans les fichiers d'en-tête, comme celui-ci pour le fichier foo.h:
la source
L'approche dans laquelle j'ai évolué en vingt ans est la suivante;
Prenons une bibliothèque.
Il existe plusieurs fichiers C, un fichier H interne et un fichier H externe. Les fichiers C incluent le fichier H interne. Le fichier H interne comprend le fichier H externe.
Vous voyez que dans le PDV des compilateurs, comme il compile un fichier C, il y a une hiérarchie;
externe -> interne -> code C
C'est le bon ordre, car ce qui est externe est tout ce dont un tiers a besoin pour utiliser la bibliothèque. Ce qui est interne est nécessaire pour compiler le code C.
la source
Si le fichier d' en- tête Un
#includes
fichiers en- tête B et C, puis chaque fichier source#includes
A sera également obtenir B et C#included
. Le pré-processeur effectue littéralement une substitution de texte: partout où il trouve du texte indiquant#include <foo.h>
qu'il le remplace par le texte dufoo.h
fichier.Il existe différentes opinions quant à savoir si vous devez insérer des
#includes
en-têtes ou des fichiers source. Personnellement, je préfère tout mettre#includes
dans le fichier source par défaut, mais tous les fichiers d'en-tête qui ne peuvent pas être compilés sans d'autres en-têtes prérequis devraient#include
ces en-têtes eux-mêmes.Et chaque fichier d'en-tête doit contenir une garde d'inclusion pour éviter qu'il ne soit inclus plusieurs fois.
la source
Dans certains environnements, la compilation sera la plus rapide si l'on n'inclut que les fichiers d'en-tête dont on a besoin. Dans d'autres environnements, la compilation sera optimisée si tous les fichiers source peuvent utiliser la même collection principale d'en-têtes (certains fichiers peuvent avoir des en-têtes supplémentaires au-delà du sous-ensemble commun). Idéalement, les en-têtes doivent être construits de sorte que plusieurs opérations #include n'aient aucun effet. Il peut être bon d'entourer les instructions #include de vérifications pour l'inclusion-guard du fichier à inclure, bien que cela crée une dépendance sur le format de cette garde. De plus, en fonction du comportement de mise en cache des fichiers d'un système, une #inclusion inutile dont la cible finit par être complètement # ifdef'ed ne peut pas prendre longtemps.
Une autre chose à considérer est que si une fonction prend un pointeur vers une structure, on peut écrire le prototype comme
sans qu'une définition pour BAR_s soit dans la portée. Une approche très pratique pour éviter les inclusions inutiles.
PS - dans beaucoup de mes projets, il y aura un fichier que chaque module devrait #include, contenant des choses comme des typedefs pour des tailles entières et quelques structures et unions courantes [par exemple
(Oui, je sais que j'aurais des problèmes si je passais à une architecture big-endian, mais comme mon compilateur n'autorise pas les structures anonymes dans les unions, l'utilisation d'identificateurs nommés pour les octets dans l'union nécessiterait qu'ils soient accessibles comme theUnion.b.b1 etc. qui semble plutôt ennuyeux.
la source
Créez tous vos fichiers afin qu'ils puissent être créés en utilisant uniquement ce qu'ils contiennent. Si vous n'avez pas besoin d'une inclusion dans votre en-tête, supprimez-la. Dans un grand projet, si vous ne maintenez pas cette discipline, vous vous laissez ouvert à la rupture d'une compilation entière lorsque quelqu'un supprime une inclusion d'un fichier d'en-tête qui est utilisé par un consommateur de ce fichier et même pas par l'en-tête.
la source
Votre fichier source aura les instructions d'inclusion si vous le mettez dans l'en-tête. Cependant, dans certains cas, il serait préférable de les mettre dans le fichier source.
N'oubliez pas que si vous incluez cet en-tête dans d'autres sources, ils obtiendront également les inclusions de l'en-tête, ce qui n'est pas toujours souhaitable. Vous ne devez inclure les éléments que là où ils sont utilisés.
la source
Vous ne devez inclure dans votre en-tête que les fichiers dont vous avez besoin pour déclarer des constantes et des déclarations de fonction. Techniquement, ces inclusions seront également incluses dans votre fichier source, mais par souci de clarté, vous ne devez inclure dans chaque fichier que les fichiers que vous devez réellement utiliser. Vous devez également les protéger dans votre en-tête de l'inclusion multiple ainsi:
Cela empêche l'en-tête d'être inclus plusieurs fois, ce qui entraîne une erreur du compilateur.
la source