Quel ordre doit inclure les fichiers à spécifier, c'est-à-dire quelles sont les raisons d'inclure un en-tête avant un autre?
Par exemple, les fichiers système, STL et Boost vont-ils avant ou après les fichiers include locaux?
Quel ordre doit inclure les fichiers à spécifier, c'est-à-dire quelles sont les raisons d'inclure un en-tête avant un autre?
Par exemple, les fichiers système, STL et Boost vont-ils avant ou après les fichiers include locaux?
Réponses:
Je ne pense pas qu'il y ait un ordre recommandé, tant qu'il compile! Ce qui est ennuyeux, c'est lorsque certains en-têtes exigent que d'autres en-têtes soient inclus en premier ... C'est un problème avec les en-têtes eux-mêmes, pas avec l'ordre des inclusions.
Ma préférence personnelle est de passer du local au global, chaque sous-section par ordre alphabétique, c'est-à-dire:
Mon raisonnement pour 1. est qu'il devrait prouver que chaque en-tête (pour lequel il y a un cpp) peut être #include
d sans prérequis (terminus technicus: l'en-tête est "autonome"). Et le reste semble découler logiquement de là.
La grande chose à garder à l'esprit est que vos en-têtes ne doivent pas dépendre des autres en-têtes inclus en premier. Une façon de garantir cela est d'inclure vos en-têtes avant tout autre en-tête.
"Penser en C ++" le mentionne en particulier, en faisant référence au "Large Software C ++ Software Design" de Lakos:
Les erreurs d'utilisation latentes peuvent être évitées en s'assurant que le fichier .h d'un composant est analysé par lui-même - sans déclarations ni définitions fournies en externe ... L'inclusion du fichier .h en tant que toute première ligne du fichier .c garantit qu'aucune pièce critique des informations intrinsèques à l'interface physique du composant sont manquantes dans le fichier .h (ou, le cas échéant, vous en serez informé dès que vous tenterez de compiler le fichier .c).
C'est-à-dire, inclure dans l'ordre suivant:
Si l'un des en-têtes a un problème avec l'inclusion dans cette commande, corrigez-les (si le vôtre) ou ne les utilisez pas. Libérez les bibliothèques qui n'écrivent pas d'en-têtes propres.
Le guide de style C ++ de Google soutient presque l'inverse, sans vraiment aucune justification; Personnellement, j'ai tendance à privilégier l'approche Lakos.
Je respecte deux règles simples qui évitent la grande majorité des problèmes:
Je respecte également les directives de:
En d'autres termes:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
Bien que, étant des lignes directrices, c'est une chose subjective. D'un autre côté, j'applique les règles de manière rigide, même au point de fournir des fichiers d'en-tête 'wrapper' avec des gardes d'inclusion et des inclusions groupées si un développeur tiers désagréable ne souscrit pas à ma vision :-)
Pour ajouter ma propre brique au mur.
Donc je vais généralement comme ceci:
// myproject/src/example.cpp
#include "myproject/example.h"
#include <algorithm>
#include <set>
#include <vector>
#include <3rdparty/foo.h>
#include <3rdparty/bar.h>
#include "myproject/another.h"
#include "myproject/specific/bla.h"
#include "detail/impl.h"
Chaque groupe séparé par une ligne vierge du suivant:
Notez également que, à part les en-têtes système, chaque fichier se trouve dans un dossier avec le nom de son espace de noms, simplement parce qu'il est plus facile de les retrouver de cette façon.
#define
de ceux qui gâchent d'autres codes) et pour empêcher les dépendances implicites. Par exemple, si notre fichier d'en-tête de base de code foo.h
dépend vraiment <map>
mais que partout où il a été utilisé dans des .cc
fichiers, <map>
était déjà inclus, nous ne le remarquerions probablement pas. Jusqu'à ce que quelqu'un essaie d'inclure foo.h
sans d'abord inclure <map>
. Et puis ils seraient ennuyés.
.h
a au moins un .cpp
qui l'inclut en premier (en effet, dans mon code personnel, le test unitaire associé l'inclut d'abord, et le code source l'inclut dans son groupe légitime ). En ce qui concerne le fait de ne pas être influencé, si l'un des en-têtes inclut, <map>
alors tous les en-têtes inclus par la suite sont influencés de toute façon, donc cela me semble une bataille perdue.
Header corresponding to this cpp file first (sanity check)
. Y a-t-il quelque chose de particulier s'il #include "myproject/example.h"
est déplacé à la fin de tous les inclusions?
Je recommande:
Et bien sûr, l'ordre alphabétique dans chaque section, si possible.
Utilisez toujours des déclarations avancées pour éviter les #include
s inutiles dans vos fichiers d'en-tête.
Je suis presque sûr que ce n'est pas une pratique recommandée partout dans le monde sain d'esprit, mais j'aime aligner le système en fonction de la longueur du nom de fichier, trié lexicalement dans la même longueur. Ainsi:
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
Je pense que c'est une bonne idée d'inclure vos propres en-têtes avant les autres peuples, pour éviter la honte de la dépendance des ordres d'inclusion.
windows.h
.
Ce n'est pas subjectif. Assurez-vous que vos en-têtes ne dépendent pas d'être #include
d dans un ordre spécifique. Vous pouvez être sûr que peu importe l'ordre dans lequel vous incluez les en-têtes STL ou Boost.
Commencez par inclure l'en-tête correspondant au .cpp ... en d'autres termes, source1.cpp
devrait inclure source1.h
avant d'inclure autre chose. La seule exception à laquelle je peux penser est lorsque vous utilisez MSVC avec des en-têtes précompilés, auquel cas, vous êtes obligé d'inclure stdafx.h
avant toute autre chose.
Raisonnement: l' inclusion de source1.h
tout autre fichier avant garantit qu'il peut être autonome sans ses dépendances. Si source1.h
prend une dépendance à une date ultérieure, le compilateur vous alertera immédiatement pour ajouter les déclarations avancées requises à source1.h
. Cela garantit à son tour que les en-têtes peuvent être inclus dans n'importe quel ordre par leurs personnes à charge.
Exemple:
source1.h
class Class1 {
Class2 c2; // a dependency which has not been forward declared
};
source1.cpp
#include "source1.h" // now compiler will alert you saying that Class2 is undefined
// so you can forward declare Class2 within source1.h
...
Utilisateurs MSVC: je recommande fortement d'utiliser des en-têtes précompilés. Donc, déplacez toutes les #include
directives pour les en-têtes standard (et les autres en-têtes qui ne changeront jamais) vers stdafx.h
.
Inclure du plus spécifique au moins spécifique, en commençant par le .hpp correspondant pour le .cpp, s'il en existe un. De cette façon, toutes les dépendances cachées dans les fichiers d'en-tête qui ne sont pas autosuffisantes seront révélées.
Cela est compliqué par l'utilisation d'en-têtes précompilés. Une façon de contourner cela, sans rendre votre compilateur de projet spécifique, consiste à utiliser l'un des en-têtes de projet comme fichier d'inclusion d'en-tête précompilé.
C'est une question difficile dans le monde C / C ++, avec autant d'éléments au-delà de la norme.
Je pense que l'ordre des fichiers d'en-tête n'est pas un problème sérieux tant qu'il se compile, comme l'a dit squelart.
Mes idées sont les suivantes: s'il n'y a pas de conflit de symboles dans tous ces en-têtes, tout ordre est OK et le problème de dépendance d'en-tête peut être résolu plus tard en ajoutant des lignes #include au .h défectueux.
Le vrai problème survient lorsqu'un en-tête modifie son action (en vérifiant les conditions #if) en fonction des en-têtes ci-dessus.
Par exemple, dans stddef.h dans VS2005, il y a:
#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Maintenant, le problème: si j'ai un en-tête personnalisé ("custom.h") qui doit être utilisé avec de nombreux compilateurs, y compris certains anciens qui ne fournissent pas offsetof
dans leurs en-têtes système, je devrais écrire dans mon en-tête:
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
Et assurez-vous d'indiquer à l'utilisateur #include "custom.h"
après tous les en-têtes du système, sinon la ligne de offsetof
stddef.h affirmera une erreur de redéfinition de macro.
Nous prions de ne plus rencontrer de tels cas dans notre carrière.