Bonjour,
supposons que dans un fichier d'en tête j'ai besoin de foo.h et de bar.h
Mais que bar.h inclut déjà foo.h (donc je peux me contenter d'inclure seulement bar.h).
Est-ce que j'inclus les deux ou seulement bar.h ?
Merci.
Bonjour,
supposons que dans un fichier d'en tête j'ai besoin de foo.h et de bar.h
Mais que bar.h inclut déjà foo.h (donc je peux me contenter d'inclure seulement bar.h).
Est-ce que j'inclus les deux ou seulement bar.h ?
Merci.
Pour moi, la règle est assez simple :
- Si tu as besoin d'un composant de bar.h, tu inclus bar.h
- Si tu as besoin d'un composant de foo.h, tu inclus foo.h
Si bar.h a besoin d'un composant de foo.h il doit l'inclure. Un include file devrait être complet et ne devrait forcer l'utilisateur à rechercher ce dont à besoin bar.h pour l'inclure avant.
De toute façon, si foo.h est inclus 2 fois (par ton module et par bar.h inclus par ton module), cela ne doit pas poser de problème non plus.
+1 ... J'inclus les fichiers qu'il faut quand il faut. De toute manière, si tu inclus le même fichier dans différents headers ou sources, si c'est bien fait (protection contre les inclusions multiples) y'a aucun problème !
Mon Site
Ma bibliothèque de gestion des chaînes de caractères en C
L'imagination est plus importante que le savoir. A. Einstein
Je ne répond à aucune question technique par MP, merci d'avance !
Il y en a pourtant un, de problème : ralentissement pouvant être très sensible de la vitesse de compilation, et pollution assez lourde d'un graphe de dépendance si l'on décide (ou que l'on a l'habitude) d'en utiliser... Ce qui pose d'énormes problèmes d'ailleurs lorsque l'on veut effectuer la séparation d'un module en deux parties, ou simplement analyser les dépendances.
Pour ma part, c'est plutôt le contraire : je vise à vérifier / m'assurer que l'on n'inclus pas les entêtes de façon inutile et/ou redondante.
Par contre, je vise également à ce que les entêtes .H soient complets (= ne requièrent pas d'inclusions additionnelles dans un C/CPP qui les utiliseraient) : il est donc hors de question de supprimer une inclusion "comme ça", il faut malgré tout que la chaîne d'inclusion totale soit correcte ET complète.
Mac LAK.
___________________________________________________
Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.
Sources et composants Delphi sur mon site, L'antre du Lak.
Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.
Rejoignez-nous sur : ► Serveur de fichiers [NAS] ► Le Tableau de bord projets ► Le groupe de travail ICMO
Bonjour,
- Sémantiquement, tu dois inclure le fichier qui définit l'entité que tu utilises ;
- Techniquement, rien ne garantit la manière dont le fichier inclus sera écrit. D'une plate-forme à l'autre, il se peut très bien que le sous-fichier inclus ne le soit plus. Il faut donc agir comme si tu ne pouvais voir l'intérieur de ce fichier.
Plus précisément, il n'y a pas de relation hiérarchique entre les *.h comme il y en a dans un arbre de classes objet, par exemple. bar.h « n'implique pas » foo.h. Par ailleurs, la directive #include sert à inclure n'importe quoi, pas forcément des *.h. C'est assez rare de voir autre chose, bien sûr, mais c'est le cas avec les *.xpm, par exemple.
Pour éviter que le contenu d'un *.h soit redéfini plusieurs fois, on l'encadre généralement avec des macros du genre :
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 #ifndef FOO_H #define FOO_H 1 ... [contenu] ... #endif
Il te faudra penser à le faire à ton tour si, toi aussi, tu écris une bibliothèque et fournis son *.h.
Ce n'est pas sa question : il ne s'agit pas de coller des headers classique pour l'hygiène mais, au contraire, de savoir s'il faut volontairement omettre un header requis parce qu'un autre est réputé l'avoir inclus lui-même auparavant. La réponse est « non », pour les raisons exposées ci-dessus.
Pour les délais de compilation, aucun overhead notable n'est introduit si le fichier est encadré par les bonnes macros. Son interprétation prend fin dès le départ, lorsque la ligne idoine est atteinte. Pour les graphes des dépendances, celles-ci peuvent former un cycle sans que ce soit forcément une erreur. C'est donc à toi (ou à ton logiciel traceur) de conserver une liste de chaque fichier inclus et d'interrompre la progression de la recherche lorsqu'il est fait référence à un fichier de cette liste.
Chose pourtant classiquement faite sur pas mal d'entêtes standards et/ou d'OS... Typiquement, si tu développes sous Windows, je pense que tu auras rarement inclus "winbase.h" et que tu inclus directement "windows.h"...
Pour le "réputé", il y a aussi le fait d'avoir des entêtes complets sans scories (= TOUS les entêtes requis par l'utilisation du .H, et SEULEMENT ces entêtes). Donc, il n'y a pas de "réputé" : si tu utilises un module XX qui manipule des std::string, il est inutile d'inclure toi-même <string> : le header "XX.h" le fait pour toi, s'il est complet. Et tu peux généraliser ça à toute sous-classe, entité ou type manipulé par la classe que tu as utilisée.
Si par contre tu "profites" d'une inclusion de <string> via un header qui ne manipule pas publiquement de chaînes, là, c'est effectivement mauvais de conserver cette inclusion : il faudrait la supprimer du header qui ne l'utilise pas.
L'absence de macros peut (et souvent, va) provoquer des warnings au mieux, des erreurs au pire. Pour le reste, le fichier est malgré tout inclus et passé au préproc, même s'il ne génère que des lignes vides. Si c'est juste un .H à toi de 20 lignes, ce n'est pas trop grave. Si c'est "windows.h" et toute sa tripaille que tu inclus N fois pour rien, ça commence à devenir nettement plus sérieux, et plus tu multiplies ce phénomène, plus l'impact est lourd. Pour ma part, je vois nettement le souci sur les inclusions des entêtes ACE, par exemple : en rajouter "pour rien", c'est un ralentissement sensible de la vitesse de compilation... Surtout que si tu exagères un peu trop, tu finis par avoir besoin de swapper. OK, les fichiers peuvent être dans le cache, mais sur une très (trop ?) grosse partie, tu vas te retrouver avec deux processus qui réclament la RAM : le compilateur pour le fichier en cours de compilation, et le cache pour les maintenir disponibles.
Fais le test avec cet entête :Si tu l'inclus plusieurs fois, tu le verras plusieurs fois définies dans le fichier prétraité (-E), et les numéros de ligne vérifiés (et affichés) à chaque inclusion de cet entête. Suivant le compilateur et les réglages, tu auras ou non les lignes vides maintenues dans le fichier prétraité.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 const int TEST_INCLUDE_START = 0 ; #ifndef TEST_INCLUDE #define TEST_INCLUDE // Rajouter N lignes vides et/ou copier ce commentaire #endif const int TEST_INCLUDE_END = 1 ;
En l'occurrence, Doxygen n'effectue pas cette coupe (et heureusement, d'ailleurs, ça permet aussi de résoudre des problèmes de complétude des entêtes). Quant aux dépendances cycliques (ou encore pire : inutiles), c'est de toutes façons quelque chose d'assez crasseux pour laquelle il est quand même souhaitable de se poser la question "ai-je correctement fait ma conception de modules ?"...
Mac LAK.
___________________________________________________
Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.
Sources et composants Delphi sur mon site, L'antre du Lak.
Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.
Rejoignez-nous sur : ► Serveur de fichiers [NAS] ► Le Tableau de bord projets ► Le groupe de travail ICMO
Partager