Quelles sont les directives de codage C++ et d'organisation de fichiers que vous suggérez pour les personnes qui doivent gérer de nombreuses classes interdépendantes réparties sur plusieurs fichiers source et en-tête?
J'ai cette situation dans mon projet et résoudre les erreurs liées à la définition de classe traversant plusieurs fichiers d'en-tête est devenu un vrai casse-tête.
Quelques directives générales:
foo.cxx
, tout ce qui y est défini devrait être déclaré dans foo.h
.#include
s autant que possible. Cela vous permet de rompre les dépendances cycliques de l'en-tête. Essentiellement, pour les dépendances cycliques sur des fichiers distincts, vous voulez un graphique de dépendance de fichier qui ressemble à ceci: A.cxx
a besoin A.h
et B.h
B.cxx
a besoin A.h
et B.h
A.h
a besoin B.h
B.h
est indépendant (et déclare en amont les classes définies dans A.h
)Si votre code est destiné à être une bibliothèque consommée par d'autres développeurs, certaines étapes supplémentaires sont importantes à suivre:
include/
et src/
sous-répertoires de mes projets C ou C++, où include/
a tous mes en-têtes publics, et src/
a toutes mes sources. et en-têtes privés.Je recommanderais de trouver une copie du livre de John Lakos Large-Scale C++ Software Design. C'est un livre assez lourd, mais si vous parcourez simplement certaines de ses discussions sur l'architecture physique, vous apprendrez beaucoup.
Consultez les normes de codage C et C++ au NASA Goddard Space Flight Center . La seule règle que j'ai spécialement notée dans la norme C et que j'ai adoptée dans mon propre code est celle qui applique la nature "autonome" des fichiers d'en-tête. Dans le fichier d'implémentation xxx.cpp pour l'en-tête xxx.h, assurez-vous que xxx.h est le premier en-tête inclus. Si l'en-tête n'est pas autonome à tout moment, la compilation échouera. C'est une règle magnifiquement simple et efficace.
La seule fois où il vous échoue, c'est si vous transférez entre les machines et que l'en-tête xxx.h inclut, par exemple, <pqr.h>
, mais <pqr.h>
nécessite des installations qui sont mises à disposition par un en-tête <abc.h>
sur la plate-forme d'origine (donc <pqr.h>
comprend <abc.h>
), mais les installations ne sont pas mises à disposition par <abc.h>
sur l'autre plate-forme (ils sont dans def.h
à la place, mais <pqr.h>
n'inclus pas <def.h>
). Ce n'est pas une faute de la règle, et le problème est plus facilement diagnostiqué et résolu si vous suivez la règle.
Vérifiez la section du fichier d'en-tête dans guide de style Google
la réponse de Tom est excellente!
La seule chose que j'ajouterais est de ne jamais avoir "à l'aide de déclarations" dans les fichiers d'en-tête. Ils ne doivent être autorisés que dans les fichiers d'implémentation, par exemple foo.cpp
.
La logique est bien décrite dans l'excellent livre "Accelerated C++" ( lien Amazon - aseptisé pour les nazis de script pour les enfants)
Je voudrais ajouter une très bonne pratique (à la fois en C et C++) qui est souvent abandonnée:
#include "foo.h" // always the first directive
Tous les autres en-têtes nécessaires devraient suivre, puis coder. Le fait est que vous avez presque toujours besoin de cet en-tête pour cette unité de compilation de toute façon et l'inclure comme première directive garantit que l'en-tête reste auto-suffisant (sinon, il y aura des erreurs). Cela est particulièrement vrai pour les en-têtes publics.
Si à tout moment vous devez mettre quelque chose avant cette inclusion d'en-tête (sauf les commentaires bien sûr), il est probable que vous faites quelque chose de mal. Sauf si vous savez vraiment ce que vous faites ... ce qui conduit à une autre règle plus cruciale => commentez vos hacks!
Un point en plus des autres ici:
N'incluez aucune définition privée dans un fichier include. Par exemple. toute définition qui n'est utilisée que dans xxx.cpp doit être dans xxx.cpp, pas xxx.h.
Cela semble évident, mais je le vois souvent.