2011-12-03 1 views
2

Quand j'inclure un fichier d'en-tête, permet de dire,Confusion avec y compris les fichiers d'en-tête

//myheader.h 
#ifndef MY_HEADER_H 
#define MY_HEADER_H 

//.... 

#endif 

dans,

//mycpp1.cpp 
#include "myheader.h" 

Ce que je dis est, quand mycpp1.cpp comprend myheader.h, MY_HEADER_H est défini de sorte que toute tentative de l'inclure à nouveau entraînera faux.

Maintenant, si je veux l'inclure dans mycpp2.cpp.

//mpcpp2.cpp 
#include "myheader.h" 

Serait-il inclus ou utilise-t-il les mêmes déclarations quand il a été inclus la première fois?

Répondre

6

Les définitions de préprocesseur sont séparées pour chaque fichier. Donc, si vous #include myheader.h en deux fichiers .cpp séparés, il sera inclus deux fois, pas une fois. Un par .cpp.

+0

C'est ce que je devinais ... est-il possible de vérifier si elle est incluse deux fois? – user103214

+0

@ user974191 vous pouvez regarder les fichiers après que le préprocesseur se soit terminé avec eux, mais pourquoi voulez-vous? –

+0

Voulez-vous dire les fichiers objets? Rien que d'essayer de comprendre ce qui se passe. – user103214

3

Si MY_HEADER_H est juste défini dans mycpp1.cpp, le fichier d'en-tête sera inclus dans mycpp2.cpp

ce que le truc est vraiment est comme:

header1.h comprend header2.h.
Ainsi, lorsque vous comprennent à la fois header1.h et header2.h dans votre mycpp.cpp, header2.h seront inclus deux fois si vous ne l'avez pas l'affaire.

-1

Il sera inclus une seule fois. La directive MY_HEADER_H serait définie à la première inclusion et toutes les tentatives suivantes de #include myheader.h n'auraient aucun effet.

Les directives du préprocesseur prévalent sur les fichiers. Sinon, par exemple, chaque classe déclarée dans myheader.h serait redéfinie.

1

Comme l'ont indiqué les autres, le fichier d'en-tête est inclus une fois par fichier .cpp. Mais je voulais aussi mentionner que le but de cette:

#ifndef MY_HEADER_H 
#define MY_HEADER_H 
// .. 
#end if 

est d'éviter que cela provoque un problème

mycpp1.cpp

#include "myheader.h" 
#include "myheader.h" 
// ... 

autre chose que j'ai eu du mal avec quand j'ai commencé, quand vous avez inclus votre fichier d'en-tête dans plusieurs fichiers .cpp et que vous y avez défini des variables globales ... voici ce que je fais pour résoudre ça ...

myheader.h

#ifdef MY_HEADER_H 
#define MY_HEADER_H 

#ifdef GLOBAL_EXTERN 
extern int nGlobalInt; 
#else 
int nGlobalInt = 282; 
#endif 

#endif 

mycpp1.cpp

#include "myheader.h" 
// ... 

cout << nGlobalInt; 

mycpp2.cpp

#define GLOBAL_EXTERN 
#include "myheader.h" 
// ... 

cout << nGlobalInt; 

les deux fichiers cpp imprimeront 282

+0

Sans le '#ifdef GLOBAL_EXTERN ...' vous obtiendrez une erreur de redéfinition avec votre compilateur. –

+0

c'est plus simple si vous définissez 'nGlobalInt' dans * un * des fichiers cpp et que vous vous débarrassez de 'GLOBAL_EXTERN'. extern agit comme une déclaration directe pour cette instance de variable. – greatwolf

+0

@Victor T., d'accord ... Mais pour les contextes de cette question, j'ai pensé que cet exemple serait meilleur. –

4

définit préprocesseur sont locaux à l'unité de compilation en cours.

Bien sûr, il y a des cas complexes, mais voici le point:

Essayez de regarder .CPP (source) comme des entités distinctes. Si vous ne faites pas des choses vraiment étranges, puis si vous supprimez tous les fichiers .cpp sauf celui que vous dérangez, vous pouvez encore compiler, car dans la phase de compilation pas besoin pour les définitions, vous vous souciez seulement du nom (déclaration) des choses.

Ainsi, la compilation de fichiers source N dans une course est essentiellement ceci:

[ *.H + SOURCE1.CPP ] --> SOURCE1.O 
[ *.H + SOURCE2.CPP ] --> SOURCE2.O 
... 
[ *.H + SOURCEN.CPP ] --> SOURCEN.O 

où chaque ligne est une unité de compilation distincte, qui rend le SourceX.CPP et les en-têtes inclus dans un fichier d'objets . Donc, nous sommes arrivés ici N chose séparée. Ainsi, si vous ne modifiez pas les en-têtes communs, vous n'avez pas besoin de recompiler les fichiers source non modifiés. Bien sûr, si vous modifiez un fichier source, vous devez le recompiler. Et enfin, si vous modifiez un en-tête commun, vous avez pour recompiler tous les fichiers source qui l'ont inclus. Ici, je dois mentionner, qu'avant la phase de compilation, tous les #inlude "filename.ext" ligne (directive préprocesseur) seront remplacés avec le contenu exact du fichier filename.ext, quel qu'il soit.

Ensuite, la liaison est un problème différent, dans ce stade le but est de créer un seul fichier à partir de ce N fichiers objet. (je le répète, cela est le cas simple)

C'est un lien:

[ SOURCE1.O + SOURCE2.O + ... + SOURCEN.O ] --> EXECUTABLE.FILE 

Imaginez l'affecté les fichiers objet comme un sac de valeurs et algorithmes (fonction définitions). Par exemple, quelque part dans le sac il doit y avoir exactement une main fonction (définition), de sorte que le lieur va certainement savoir ce que à faire lorsque vous exécutez le programme.

espère que vous l'avez

Devinez ce qui arrive, si vous écrivez une définition de fonction globale dans un fichier d'en-tête, et vous inclure dans deux unités de compilation séparée, alors vous essayez de les relier.

L'erreur Answerer: plusieurs définitions, puisque vous pouvez les compiler séparément.