web-dev-qa-db-fra.com

Déclaration à terme vs inclure

Reduce the number of #include files in header files. It will reduce build times. Instead, put include files in source code files and use forward declarations in header files.

J'ai lu ça ici. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html .

Il indique donc si une classe (classe A) dans le fichier d'en-tête n'a pas besoin d'utiliser la définition réelle d'une classe (classe B). À ce moment, nous pouvons utiliser la déclaration directe au lieu d'inclure le fichier d'en-tête particulier (classe B).

Question: Si la classe (classe A) dans l'en-tête n'utilise pas la définition réelle d'une classe particulière (classe B), alors comment la déclaration directe contribue à réduire le temps de compilation?

18
Nayana Adassuriya

Le compilateur ne se soucie pas si la classe A utilise la classe B. Il sait seulement que lorsque la classe A est compilée et qu'il n'a pas de déclaration préalable de classe B (déclaration directe ou autre), il panique et le marque comme une erreur.

Ce qui est important ici, c'est que le compilateur sait que vous n'avez pas essayé de compiler un programme après que votre chat a marché sur votre clavier et créé des lettres aléatoires qui peuvent ou non être interprétées comme une classe.

Lorsqu'il voit une inclusion, pour pouvoir utiliser toutes les informations qu'il contient, il doit ouvrir le fichier et l'analyser (qu'il ait ou non réellement besoin de le faire). Si ce fichier comprend alors d'autres fichiers, ceux-ci doivent également être ouverts et analysés, etc. Si cela peut être évité, il est généralement préférable d'utiliser une déclaration directe à la place.

Edit: L'exception à cette règle étant les en-têtes précompilés. Dans ce cas, tous les en-têtes sont compilés et enregistrés pour de futures compilations. Si les en-têtes ne changent pas, le compilateur peut utiliser intelligemment les en-têtes précompilés des compilations précédentes et ainsi réduire les temps de compilation, mais cela ne fonctionne bien que si vous n'avez pas souvent besoin de changer les en-têtes.

12
Neil

car alors A.hpp n'a pas besoin de #inclure B.hpp

donc A.hpp devient

class B;//or however forward decl works for classes

class A
{
    B* bInstance_;
//...
}

donc quand A.hpp est inclus alors B.hpp n'est pas implicitement inclus et tous les fichiers qui dépendent uniquement de A.hpp n'ont pas besoin d'être recompilés à chaque fois que b.hpp change

4
ratchet freak

N'oubliez pas que le préprocesseur C/C++ est une étape de traitement distincte, purement textuelle. La directive #include Extrait le contenu de l'en-tête inclus et le compilateur doit l'analyser. De plus, la compilation de chaque .cpp Est complètement distincte, donc le fait que le compilateur vient d'analyser B.h Lors de la compilation de B.cpp Ne l'aide pas du tout lorsqu'il en a de nouveau besoin lors de la compilation A.cpp. Et encore lors de la compilation de C.cpp. Et D.cpp. Etc. Et chacun de ces fichiers doit être recompilé si l'un des fichiers qu'il contient a changé.

Par exemple, la classe A utilise la classe B et les classes C et D utilisent la classe A, mais n'ont pas besoin de manipuler B. Si la classe A peut être déclarée avec une simple déclaration directe de B, alors B.h Est compilé deux fois: lors de la compilation de B.cpp Et A.cpp (car B est toujours nécessaire dans les méthodes de A).

Mais lorsque A.h Inclut B.h, Il est compilé quatre fois - lors de la compilation de B.cpp, A.cpp, C.cpp et D.cpp car les deux derniers incluent désormais indirectement B.h.

De plus, lorsque l'en-tête est inclus plusieurs fois, le préprocesseur doit toujours le lire chaque fois. Il sautera le traitement de son contenu en raison des #ifdef De garde, mais il le lit toujours et doit rechercher la fin de la garde, ce qui signifie qu'il doit analyser toutes les directives du préprocesseur à l'intérieur.

(Comme mentionné dans l'autre réponse, les en-têtes précompilés tentent de contourner ce problème, mais ils sont leur propre boîte de vers; en gros, vous pouvez raisonnablement les utiliser pour les en-têtes du système et uniquement si vous n'en utilisez pas trop, mais pas pour en-têtes de votre projet)

3
Jan Hudec

Une déclaration directe est beaucoup plus rapide à analyser qu'un fichier d'en-tête entier qui lui-même peut inclure encore plus de fichiers d'en-tête.

De plus, si vous modifiez quelque chose dans le fichier d'en-tête pour la classe B, tout ce qui comprend cet en-tête devra être recompilé. Avec une déclaration directe, il ne peut s'agir que du fichier source dans lequel l'implémentation de A réside. Mais si l'en-tête de A inclut réellement l'en-tête de B, tout, y compris a.hpp sera également recompilé, même s'il n'utilise rien de B.

2
Benjamin Kloster