Lorsque vous divisez votre code en plusieurs fichiers, qu'est-ce qui devrait exactement entrer dans un fichier .h et que devrait-il entrer dans un fichier .cpp?
c++
header-files
Enrico Tuvera Jr
la source
la source
.hpp
fichier tandis que les déclarations C vont dans un.h
fichier. Ceci est très utile lors du mélange de code C et C ++ (par exemple des modules hérités en C).Réponses:
Les fichiers d'en-tête (
.h
) sont conçus pour fournir les informations qui seront nécessaires dans plusieurs fichiers. Des éléments tels que les déclarations de classe, les prototypes de fonctions et les énumérations se trouvent généralement dans les fichiers d'en-tête. En un mot, «définitions».Les fichiers de code (
.cpp
) sont conçus pour fournir les informations d'implémentation qui ne doivent être connues que dans un seul fichier. En général, les corps de fonctions et les variables internes qui ne devraient / ne seront jamais accessibles par d'autres modules, sont ce qui appartient aux.cpp
fichiers. En un mot, «implémentations».La question la plus simple à se poser pour déterminer ce qui appartient à où est "si je change cela, devrai-je changer le code dans d'autres fichiers pour que les choses se compilent à nouveau?" Si la réponse est «oui», elle appartient probablement au fichier d'en-tête; si la réponse est «non», elle appartient probablement au fichier de code.
la source
export
). Le seul moyen de contourner le n ° 1 est PIMPL. # 2 serait possible s'ilexport
était pris en charge et pourrait être possible en utilisant C ++ 0x et desextern
modèles. OMI, les fichiers d'en-tête en C ++ perdent beaucoup de leur utilité.Le fait est qu'en C ++, c'est un peu plus compliqué que l'organisation en-tête / source C.
Que voit le compilateur?
Le compilateur voit un gros fichier source (.cpp) avec ses en-têtes correctement inclus. Le fichier source est l'unité de compilation qui sera compilée dans un fichier objet.
Alors, pourquoi les en-têtes sont-ils nécessaires?
Parce qu'une unité de compilation peut avoir besoin d'informations sur une implémentation dans une autre unité de compilation. On peut donc écrire par exemple l'implémentation d'une fonction dans une source, et écrire la déclaration de cette fonction dans une autre source ayant besoin de l'utiliser.
Dans ce cas, il existe deux copies des mêmes informations. Ce qui est mal ...
La solution est de partager quelques détails. Alors que l'implémentation doit rester dans la source, la déclaration de symboles partagés, comme les fonctions, ou la définition de structures, classes, énumérations, etc., pourrait devoir être partagée.
Les en-têtes sont utilisés pour mettre ces détails partagés.
Déplacez vers l'en-tête les déclarations de ce qui doit être partagé entre plusieurs sources
Rien de plus?
En C ++, il y a d'autres choses qui pourraient être placées dans l'en-tête car elles doivent aussi être partagées:
Déplacer vers l'en-tête TOUT ce qui doit être partagé, y compris les implémentations partagées
Cela signifie-t-il alors qu'il pourrait y avoir des sources à l'intérieur des en-têtes?
Oui. En fait, il y a beaucoup de choses différentes qui pourraient être à l'intérieur d'un "en-tête" (c'est-à-dire partagées entre les sources).
Cela devient compliqué, et dans certains cas (dépendances circulaires entre symboles), impossible de le conserver dans un en-tête.
Les en-têtes peuvent être divisés en trois parties
Cela signifie que, dans un cas extrême, vous pourriez avoir:
Imaginons que nous ayons un MyObject basé sur un modèle. Nous pourrions avoir:
.
.
.
Hou la la!
Dans la «vraie vie», c'est généralement moins compliqué. La plupart du code n'aura qu'un simple en-tête / organisation source, avec du code incorporé dans la source.
Mais dans d'autres cas (objets basés sur des modèles se connaissant les uns les autres), je devais avoir pour chaque objet des en-têtes de déclaration et d'implémentation séparés, avec une source vide comprenant ces en-têtes juste pour m'aider à voir certaines erreurs de compilation.
Une autre raison de décomposer les en-têtes en en-têtes séparés pourrait être d'accélérer la compilation, de limiter la quantité de symboles analysés au strict nécessaire et d'éviter la recompilation inutile d'une source qui ne se soucie que de la déclaration directe lorsqu'une implémentation de méthode en ligne a changé.
Conclusion
Vous devez rendre l'organisation de votre code aussi simple que possible et aussi modulaire que possible. Mettez autant que possible dans le fichier source. N'exposez dans les en-têtes que ce qui doit être partagé.
Mais le jour où vous aurez des dépendances circulaires entre des objets modèles, ne soyez pas surpris si l'organisation de votre code devient un peu plus "intéressante" que l'organisation simple en-tête / source ...
^ _ ^
la source
en plus de toutes les autres réponses, je vous dirai ce que vous NE placez PAS dans un fichier d'en-tête: la
using
déclaration (l'être le plus courantusing namespace std;
) ne doit pas apparaître dans un fichier d'en-tête car elle pollue l'espace de noms du fichier source dans lequel elle est incluse .la source
using
pour importer des éléments dans un espace de noms global dans un en-tête.static inline
en C99, en raison de quelque chose à voir avec ce qui se passe lorsque vous combinez une liaison interne avec des modèles. Les espaces de noms Anon vous permettent de «masquer» les fonctions, tout en préservant les liens externes.Ce qui se compile en rien (zéro empreinte binaire) entre dans le fichier d'en-tête.
Les variables ne se compilent pas en rien, mais les déclarations de type le font (car elles ne décrivent que le comportement des variables).
les fonctions ne le font pas, mais les fonctions en ligne le font (ou les macros), car elles produisent du code uniquement là où elles sont appelées.
les modèles ne sont pas du code, ils ne sont qu'une recette pour créer du code. donc ils vont également dans les fichiers h.
la source
En général, vous placez les déclarations dans le fichier d'en-tête et les définitions dans le fichier d'implémentation (.cpp). L'exception à cela concerne les modèles, où la définition doit également figurer dans l'en-tête.
Cette question et d'autres similaires ont été fréquemment posées sur SO - voir Pourquoi des fichiers d'en-tête et des fichiers .cpp en C ++? et fichiers d'en-tête C ++, séparation de code par exemple.
la source
Vos déclarations de classe et de fonction ainsi que la documentation et les définitions des fonctions / méthodes en ligne (bien que certains préfèrent les mettre dans des fichiers .inl séparés).
la source
Le fichier d'en-tête contient principalement un squelette de classe ou une déclaration (ne change pas fréquemment)
et le fichier cpp contient l' implémentation de classe (change fréquemment).
la source
le fichier d'en-tête (.h) doit être destiné aux déclarations de classes, de structures et de ses méthodes, de prototypes, etc. L'implémentation de ces objets est faite dans cpp.
en .h
la source
Je m'attendrais à voir:
la vraie réponse est cependant ce qu'il ne faut pas mettre:
la source
L'en-tête définit quelque chose mais ne dit rien sur l'implémentation. (Hors modèles dans ce "metafore".
Cela dit, vous devez diviser les «définitions» en sous-groupes, il existe, dans ce cas, deux types de définitions.
Maintenant, je parle bien sûr du premier sous-groupe.
L'en-tête est là pour définir la disposition de votre structure afin d'aider le reste du logiciel à utiliser l'implémentation. Vous voudrez peut-être le voir comme une "abstraction" de votre implémentation, ce qui est dit méchamment mais, je pense que cela convient assez bien dans ce cas.
Comme les affiches précédentes l'ont dit et montré que vous déclarez les zones d'utilisation privées et publiques et leurs en-têtes, cela inclut également les variables privées et publiques. Maintenant, je ne veux pas entrer dans la conception du code ici, mais vous voudrez peut-être considérer ce que vous mettez dans vos en-têtes, car c'est la couche entre l'utilisateur final et l'implémentation.
la source
la source
En-tête (.h)
Corps (.cpp)
En règle générale, vous mettez la partie "partagée" du module sur le .h (la partie que les autres modules doivent pouvoir voir) et la partie "non partagée" sur le .cpp
PD: Oui, j'ai inclus des variables globales. Je les ai utilisés quelques fois et il est important de ne pas les définir sur les en-têtes, sinon vous aurez beaucoup de modules, chacun définissant sa propre variable.
EDIT: Modifié après le commentaire de David
la source