Ordre D'en-tête C++ [fermé]

quel ordre les en-têtes doivent-ils être déclarés dans un fichier header / cpp? De toute évidence, les en-têtes requis par les en-têtes subséquents devraient être plus anciens et les en-têtes propres à une classe devraient être dans la portée du RPC et non dans la portée de l'en-tête, mais y a-t-il une convention ou une pratique exemplaire d'ordre établi?

33
demandé sur Deduplicator 2009-03-05 13:49:40

10 réponses

Dans un fichier d'en-tête, vous devez inclure TOUS les en-têtes pour le rendre compilable. Et n'oubliez pas d'utiliser des déclarations forward au lieu de quelques en-têtes.

dans un fichier source:

  • correspondait fichier d'en-tête
  • en-têtes de projet nécessaires
  • bibliothèques de tiers en-têtes
  • en-têtes de bibliothèques standard
  • en-têtes de système

dans cet ordre vous ne manquerez aucun de vos fichiers d'en-tête qui ont oublié d'inclure les bibliothèques par leurs propres.

60
répondu Mykola Golubyev 2009-03-05 11:21:35

Bonne pratique: chaque .le fichier h devrait avoir un .rpc qui comprend .h premier avant toute autre chose. Cela prouve que tous .h fichier peut être mis en premier.

même si l'en-tête ne nécessite aucune implémentation, vous faites un .rpc qui comprend juste que .h fichier et rien d'autre.

cela signifie que vous pouvez répondre à votre question comme vous le souhaitez. Peu importe l'ordre dans lequel vous les incluez.

pour d'autres bons conseils, essayez ce livre: Large-Scale C++ Software Design - c'est dommage que ce soit si cher, mais c'est pratiquement un guide de survie pour la disposition du code source C++.

20
répondu Daniel Earwicker 2009-03-05 12:57:14

dans les fichiers d'en-tête, j'ai tendance à placer les en-têtes standards en premier, puis mes propres en-têtes (les deux listes étant classées par ordre alphabétique). Dans les fichiers d'implémentation, je mets d'abord l'en-tête correspondant (le cas échéant), puis les en-têtes standards et autres en-têtes de dépendances.

ordre est de peu d'importance, sauf si vous faites une grande utilisation de macros et #define ; dans ce cas, vous devez vérifier qu'une macro que vous avez défini ne remplace pas un précédemment inclus (sauf si c'est ce que vous voulez, bien sûr).

concernant cette déclaration

ceux qui sont requis par les en-têtes suivants devraient être plus tôt

un en-tête ne devrait pas compter sur d'autres en-têtes inclus avant lui! Si elle nécessite des en-têtes, il comprend. En-tête de gardes de prévenir plusieurs inclusion:

#ifndef FOO_HEADER_H
#define FOO_HEADER_H
...
#endif

modifier

depuis que j'ai écrit cette réponse, j'ai changé ma façon d'ordonner les directives include dans mon code. Maintenant, j'essaie de Toujours mettre les en-têtes dans un ordre croissant de standardisation, de sorte que les en-têtes de mon projet viennent en premier, suivis par des en-têtes de bibliothèques tierces, suivis par des en-têtes standards.

par exemple, si l'un de mes fichiers utilise une bibliothèque que j'ai écrite, Qt, Boost et la bibliothèque standard, je commanderai les includes comme suit:

//foo.cpp
#include "foo.hpp"

#include <my_library.hpp>
// other headers related to my_library

#include <QtCore/qalgorithms.h>
// other Qt headers

#include <boost/format.hpp> // Boost is arguably more standard than Qt
// other boost headers

#include <algorithms>
// other standard algorithms

la raison pour laquelle je fais cela est de détecter les dépendances manquantes dans mes propres en-têtes: supposons par exemple que my_library.hpp utilise std::copy , mais n'inclut pas <algorithm> . Si je l'inclut après <algorithm> dans foo.cpp , cette dépendance manquante passera inaperçue. Au contraire, avec l'ordre que je viens de présenter, le compilateur se plaindra que std::copy n'a pas été déclaré, me permettant de corriger my_library.hpp .

dans chaque groupe "bibliothèque", j'essaie de garder les directives include par ordre alphabétique, pour les trouver plus facilement.

sur un sidenote, une bonne pratique est aussi de limiter au maximum la dépendance entre les fichiers d'en-tête. Les fichiers doivent inclure le moins d'en-têtes possible, particulièrement le fichier d'en-têtes. En effet, plus vous incluez d'en-têtes, plus de code doit être recompilé lorsque quelque chose change. Une bonne façon de limiter ces dépendances est d'utiliser la déclaration forward, qui est très souvent suffisamment dans les fichiers d'en-tête (voir Quand puis-je utiliser une déclaration anticipée? ).

6
répondu Luc Touraille 2017-05-23 12:34:25

Google C++ Guide de Style, noms et ordre des Includes :

in dir/foo.cc, dont le but principal est de mettre en œuvre ou tester la substance dans dir2/foo2.h, commandez vos includes comme suit:

  • dir2/foo2.h (Lieu privilégié - voir les détails ci-dessous).
  • c fichiers système.
  • C++ système de fichiers.
  • d'Autres bibliothèques .h fichiers.
  • votre projet .h fichiers.
5
répondu Igor Oks 2009-03-05 11:37:57

j'avais l'habitude de les commander en ordre alphabétique (plus facile à trouver)

3
répondu Gambrinus 2009-03-05 10:50:52

Le "comment" n'est pas évident, mais le "quoi". Votre but est de s'assurer que l'ordre dans lequel vous incluez les fichiers d'en-tête n'importe jamais (et je veux dire "jamais !").

une bonne aide est de vérifier si les fichiers d'en-tête compilent lors de la construction de fichiers cpp (un pour chaque fichier d'en-tête) qui ne comprennent qu'un seul d'entre eux.

2
répondu Benoît 2009-03-05 11:13:52

For .fichiers cpp, vous devriez inclure l'en-tête de la classe ou ce que vous êtes en train de mettre en œuvre d'abord, de sorte que vous attrapez le cas où cet en-tête manque quelques includes. Après cela, la plupart des lignes directrices de codage ont tendance à inclure les en-têtes de système en premier, les en-têtes de projet en second, par exemple le Guide de style de Google C++ .

1
répondu Anteru 2009-03-05 10:58:11

C'est une dépendance, et cela dépend en grande partie de ce que vous mettez dans nos têtes. Un fait est que vous pouvez être vraiment notoire à ce sujet et de minimiser pour garder vos includes strict, mais vous finirez par rencontrer un scénario où vous voudrez utiliser des gardes d'inclusion.

#ifndef MY_HEADER_H
#define MY_HEADER_H
//...
#endif

Le problème n'est pas évident au début, mais que la complexité de votre logiciel augmente ainsi votre dépendances. Vous pouvez faire bien, et être intelligent à ce sujet, mais les projets C++ plus grands sont généralement criblés d'inclusions. Vous pouvez essayer, mais vous ne pouvez faire beaucoup. Alors soyez diligent et pensez à vos inclusions, Oui! Mais vous aurez très certainement des dépendances cycliques à un moment donné et c'est pourquoi vous avez besoin de garde inclusion.

0
répondu John Leidegren 2009-03-05 10:53:57

si un en-tête a besoin d'autres en-têtes alors il les inclut simplement dans cet en-tête.

essayez de structurer votre code de sorte que vous passiez des pointeurs ou des références et de déclarer en avant où vous le pouvez.

dans la mise en œuvre, alors l'en-tête qui le définit devrait être listé en premier (sauf dans Visual Studio si vous utilisez pch, alors stdafx irait en premier).

en général, je les énumère comme j'en ai besoin.

0
répondu graham.reeds 2009-03-05 10:58:37

j'ai trouvé la convention suivante la plus utile:

Module

.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project

l'important est de mettre l'en-tête du module comme premier en-tête non précompilé. Cela assure "module.h " n'a pas de dépendances inattendues.

si vous travaillez sur un grand projet avec des temps d'accès lents, j'ai vu ce style utilisé pour réduire les temps de construction:

Module

.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project
#if !defined _OTHER_MODULE_GUARD_
#include "other_module.h"
#endif 

#if !defined _ANOTHER_MODULE_GUARD_
#include "another_module.h"
#endif 

c'est un peu verbeux mais économise sur la recherche disque car l'en-tête ne sera pas recherché / ouvert s'il a déjà été inclus. Sans la vérification de la garde, le compilateur va chercher et ouvrir le fichier d'en-tête, analyser l'ensemble du fichier pour finir #ifdef dans l'ensemble du fichier.

-1
répondu Skizz 2012-07-03 14:29:50