Nouveau en C ++! Je lisais donc ceci: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/
Protecteurs d'en-tête
Étant donné que les fichiers d'en-tête peuvent inclure d'autres fichiers d'en-tête, il est possible de se retrouver dans la situation où un fichier d'en-tête est inclus plusieurs fois.
Nous faisons donc des directives de préprocesseur pour éviter cela. Mais je ne suis pas sûr - pourquoi le compilateur ne peut-il pas juste ... ne pas importer deux fois la même chose?
Étant donné que les protections d'en-tête sont facultatives (mais apparemment une bonne pratique), cela me fait presque penser qu'il existe des scénarios lorsque vous souhaitez importer quelque chose deux fois. Bien que je ne puisse pas penser à un tel scénario du tout. Des idées?
#pragma once
qui indique au compilateur de n'inclure ce fichier qu'une seule fois.Réponses:
Ils peuvent, comme le montrent les nouvelles langues qui le font.
Mais une décision de conception a été prise il y a toutes ces années (lorsque le compilateur C était à plusieurs étapes indépendantes) et maintenant pour maintenir la compatibilité, le pré-processeur doit agir d'une certaine manière pour s'assurer que l'ancien code compile comme prévu.
Comme C ++ hérite de la façon dont il traite les fichiers d'en-tête de C, il a conservé les mêmes techniques. Nous soutenons une ancienne décision de conception. Mais changer la façon dont cela fonctionne est trop risqué, beaucoup de code pourrait potentiellement casser. Alors maintenant, nous devons enseigner aux nouveaux utilisateurs de la langue comment utiliser les gardes.
Il y a quelques astuces avec les fichiers d'en-tête si vous les incluez délibérément plusieurs fois (cela fournit en fait une fonctionnalité utile). Bien que si nous avons repensé le paradigme à partir de zéro, nous pourrions en faire la manière non par défaut d'inclure des fichiers.
la source
Ce ne serait pas aussi expressif autrement, étant donné qu'ils ont choisi de maintenir la compatibilité avec C et donc de continuer avec un préprocesseur plutôt qu'un système d'emballage traditionnel.
Une chose qui me vient à l'esprit est que j'avais un projet qui était une API. J'avais deux fichiers d'en-tête
x86lib.h
etx86lib_internal.h
. Parce que interne était énorme, j'ai séparé les bits "publics" en x86lib.h afin que les utilisateurs n'aient pas à réserver du temps supplémentaire pour la compilation.Cela a cependant introduit un drôle de problème avec les dépendances, donc j'ai fini par avoir un flux qui ressemblait à ceci dans x86lib_internal
Je ne dirais pas que c'était la meilleure façon de procéder, mais cela a atteint ce que je voulais.
la source
Une des difficultés de l'exclusion automatique des en-têtes en double est que la norme C est relativement silencieuse sur la signification des noms de fichiers. Par exemple, supposons que le fichier principal en cours de compilation contient des directives
#include "f1.h"
et#include "f2.h"
, et que les fichiers trouvés pour ces directives contiennent tous les deux#include "f3.h"
. Sif1.h
et sef2.h
trouvent dans des répertoires différents, mais ont été trouvés en recherchant les chemins d'inclusion, il ne serait pas clair que les#include
directives dans ces fichiers étaient destinées à charger le mêmef3.h
fichier ou des fichiers différents.Les choses empirent encore si l'on ajoute les possibilités d'inclure des fichiers incluant des chemins relatifs. Dans certains cas, lorsque les fichiers d'en-tête utilisent des chemins relatifs pour les directives d'inclusion imbriquées et que l'on souhaite éviter de modifier les fichiers d'en-tête fournis, il peut être nécessaire de dupliquer un fichier d'en-tête à plusieurs endroits dans la structure de répertoires d'un projet. Même s'il existe plusieurs copies physiques de ce fichier d'en-tête, elles doivent être considérées sémantiquement comme s'il s'agissait d'un seul fichier.
Si la
#pragma once
directive permettait à un identificateur de suivreonce
, avec la sémantique que le compilateur devrait ignorer le fichier si l'identifiant correspond à celui d'une#pragma once
directive rencontrée précédemment , alors la sémantique serait sans ambiguïté; un compilateur qui pourrait dire qu'une#include
directive chargerait le même#pragma once
fichier balisé qu'un précédent, il pourrait gagner un peu de temps en sautant le fichier sans l'ouvrir à nouveau, mais une telle détection ne serait pas sémantiquement importante car le fichier serait ignoré si ou non le nom de fichier a été reconnu comme une correspondance. Cependant, je ne connais aucun compilateur fonctionnant de cette façon. Demander à un compilateur d'observer si un fichier correspond au modèle#ifndef someIdentifier / #define someIdentifier / #endif [for that ifndef] / nothing following
et de traiter une telle chose comme équivalente à ce qui précède#pragma once someIdentifier
sisomeIdentifier
reste défini, est essentiellement aussi bon.la source