6
votes

Pourquoi est-il valide pour inclure un fichier d'en-tête deux fois en C ++?

#include "DLLDefines.h"
#include "DLLDefines.h"
The above actually passed compilation, but why?

2 commentaires

Pourquoi serait-il invalide? (Question sérieuse; essayer de voir comment vous comprenez #include .)


Pour suivre le point de Strager: #include colle le contenu du fichier fourni dans le fichier actuel. Rien d'autre (mis à part peut-être des annotations spécifiques à la mise en œuvre pour aider le compilateur à signaler les numéros de ligne pour les erreurs et émet des informations de débogage). Il n'y a aucune raison particulière de vous interdire de le faire deux fois, et les fichiers .h le supportent en utilisant comprennent les gardes.


7 Réponses :


4
votes

probablement vous en avez probablement un #define dans dlldefines.h autour de votre code qui l'empêche d'être incluse deux fois.

#ifndef DLLDEFINES_H
#define DLLDEFINES_H
// your code
#endif


4 commentaires

Nitpick: Cette technique ne l'empêche pas d'être incluse deux fois; Cela permet de l'inclure à plusieurs reprises.


@CHARDLES: Il empêche le code de l'en-tête d'être lu deux fois, ce qui est ce qui est normalement destiné à inclure un fichier.


En effet, je ne savais pas comment le dire sans surcharger l'explication. Le préprocesseur ignorera le contenu à l'intérieur du #IffnDEF la deuxième fois que le fichier est inclus.


@RUBENVB: Je comprends que, je pense juste que c'est important de ne pas faire #include semble plus magique que lorsque l'adresseur de la question doit évidemment comprendre les bases. Être strictement précis mai aider à éviter la confusion.



9
votes

Cela dépend du fichier d'en-tête; Il n'y a pas de restriction linguistique sur plusieurs inclres du même fichier.

Certains fichiers sont conçus pour être inclus à plusieurs reprises (par exemple, peut être inclus plusieurs fois pour activer 'ON' et 'OFF' affirmation ).

De nombreux fichiers sont sans danger pour être inclus à plusieurs reprises car ils sont incluent les gardes , d'autres ne doivent pas être inclus une seule fois dans une unité de traduction ou même un programme.


0 commentaires

6
votes

Inclure n'a rien à voir avec la langue C ou C ++. C'est une directive sur le préprocesseur d'apporter un fichier. Le préprocesseur ne se soucie pas de ce que le fichier est introduit et cela ne devrait pas. Il peut être parfaitement acceptable de faire cela:

void Foo::SomeFunc(int cond)
{
    switch (cond) {
    case kThisCase:
#include "longFirstCase.h"
        break;
    case kSecondCase:
#include "longSecondCase.h"
        break;
    case kThirdCase:
#include "longFirstCase.h"
#include "longSecondCase.h"
        break;
    }
}


8 commentaires

Comment vous attendez-vous à ce que cela fonctionne? #Incluant les choses en fonction des informations d'exécution?


@Shautieh, #include insère le fichier source Verbatim. Vraisemblablement, les fichiers longfirscase.h et longsecondcase.h contiennent le code C signifiant être à l'intérieur de l'interrupteur .


@Shautieh comme Strager a dit, il colle le code dans le fichier où le #include est écrit. Par exemple, cette technique est souvent utilisée de manière à inclure des parties du code autogogenéré.


Cela peut être logique d'inclure du code CPP, mais des fichiers d'en-tête? Je ne dis pas que ça ne marchera pas, mais ça ne me semble pas "juste".


@Shautieh: L'extension dans un nom de fichier n'affecte pas #include . Dans ce cas imaginaire, les fichiers .h doivent contenir certaines lignes de code destinées à être abandonnées au milieu d'une fonction. Certes, la plupart des programmeurs donneraient au fichier une extension différente, peut-être .inc .


.h est juste une extension de fichier. Vous coudl renommez-les à .CPP et #incluez-les, mais .CPP implique que le fichier peut être compilé tout seul, et certains systèmes de construction essaieront de compiler tous les fichiers .CPP qu'ils trouvent échoueraient ici que les fichiers ne sont pas contiennent du code "complet", juste des fragments.


Le préprocesseur fait partie des langues C et C ++.


@Steve: Si l'on doit vraiment inclure les implémentations de cette façon, donnant une extension telle que .InC serait un mal moindre en effet. @Soapbox: .h n'est pas "juste" une extension. Cela peut être le cas pour le préprocesseur, mais il est contre toutes les conventions sensibles de l'utiliser comme celle-ci et cela va mordre le développeur plus tôt ou tard pour cette raison.



1
votes

C'est ce qu'on appelle un Inclure la garde forte> .

#ifndef GRANDFATHER_H
#define GRANDFATHER_H

struct foo {
    int member;
};

#endif


0 commentaires

2
votes

Tant que l'inclusion multiple des fichiers d'en-tête ne violait pas ODR (une règle de définition) 3,2 $, le code est bien formé.


0 commentaires

0
votes

dlldefines.h peut aussi avoir #pragma une fois à la Top, #pragma une fois garantissant que le fichier ne soit inclus qu'une fois.


2 commentaires

C'est une extension de Microsoft uniquement, IIRC.


@Justboo selon Wikipedia , la plupart des compilateurs Support #pragma une fois



16
votes

Eh bien, c'est légal car il a em> être légal. Parce que vous incluez souvent la même en-tête plusieurs fois sans même le réaliser.

Vous pouvez inclure deux en-têtes dans un fichier .CPP, chacun d'entre eux incluant un certain nombre de fichiers, dont certains pourraient être inclus par les deux. P>

Par exemple, tous les en-têtes de bibliothèque standard (disent, string code> ou vecteur code> par exemple) sont probablement inclus dans la plupart de vos en-têtes. Donc, vous vous retrouvez rapidement avec le même en-tête inclus indirectement inclus plusieurs fois dans le même fichier. CPPP. P>

Donc en bref, il a em> au travail, ou tout le code C ++ tomberait Apart. P>

comme pour comment fonctionne em> Ça marche, généralement à travers des gardes. N'oubliez pas que #include code> effectue simplement une copie / pâte simple: elle insère le contenu du fichier d'en-tête au site #include code> site. P>

Disons donc Vous avez un fichier d'en-tête header.h code> avec le contenu suivant: p> xxx pré>

Créons maintenant un fichier CPP qui y comprend deux fois: p>

#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block
#define HEADER_H // HEADER_H is now defined

class MyClass {};// MyClass is now defined

#endif           // leaving the "if" block

#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block
//#define HEADER_H
//
//class MyClass {};
//
#endif           // end of the skipped "if" block


0 commentaires