Neu in C ++! Also las ich das hier: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/
Kopfschutz
Da Header-Dateien andere Header-Dateien enthalten können, kann es vorkommen, dass eine Header-Datei mehrmals enthalten ist.
Um dies zu vermeiden, geben wir Präprozessor-Direktiven vor. Aber ich bin mir nicht sicher - warum kann der Compiler nur ... nicht importieren , die gleiche Sache zweimal?
Angesichts der Tatsache, dass Header-Guards optional sind (aber anscheinend eine gute Vorgehensweise sind), denke ich fast, dass es Szenarien gibt, in denen Sie etwas zweimal importieren möchten. Obwohl ich mir überhaupt kein solches Szenario vorstellen kann. Irgendwelche Ideen?
#pragma once
Befehl, der den Compiler anweist, diese Datei nur einmal einzuschließen.Antworten:
Sie können, wie neue Sprachen zeigen, dies tun.
Vor all den Jahren (als der C-Compiler aus mehreren unabhängigen Phasen bestand) wurde jedoch eine Entwurfsentscheidung getroffen. Um die Kompatibilität zu gewährleisten, muss der Vorprozessor nun auf eine bestimmte Weise vorgehen, um sicherzustellen, dass alter Code wie erwartet kompiliert wird.
Da C ++ die Art und Weise erbt, wie es Header-Dateien von C verarbeitet, wurden die gleichen Techniken beibehalten. Wir unterstützen eine alte Designentscheidung. Eine Änderung der Funktionsweise ist jedoch zu riskant. Viele Codes können möglicherweise beschädigt werden. Jetzt müssen wir neuen Benutzern der Sprache beibringen, wie man Include-Guards verwendet.
Es gibt ein paar Tricks mit Header-Dateien, die Sie absichtlich mehrmals einfügen (dies bietet tatsächlich eine nützliche Funktion). Wenn wir das Paradigma jedoch von Grund auf neu entwerfen, können wir dies zur nicht standardmäßigen Methode machen, um Dateien einzuschließen.
quelle
Anders wäre es nicht so aussagekräftig, da sie sich dafür entschieden haben, die Kompatibilität mit C beizubehalten und somit mit einem Präprozessor und nicht mit einem herkömmlichen Verpackungssystem fortzufahren.
Eine Sache, die mir einfällt, ist, dass ich ein Projekt hatte, das eine API war. Ich hatte zwei Header-Dateien
x86lib.h
undx86lib_internal.h
. Da intern sehr umfangreich war, habe ich die "öffentlichen" Bits in x86lib.h getrennt, damit die Benutzer keine zusätzliche Zeit für das Kompilieren einplanen mussten.Dies führte jedoch zu einem lustigen Problem mit Abhängigkeiten, sodass ich einen Ablauf hatte, der in x86lib_internal so ablief
Ich würde nicht sagen, dass dies der beste Weg ist, aber er hat das erreicht, was ich wollte.
quelle
Eine Schwierigkeit beim automatischen Ausschluss von Duplikat-Headern besteht darin, dass der C-Standard bezüglich der Bedeutung von Include-Dateinamen relativ leise ist. Angenommen, die zu kompilierende Hauptdatei enthält Direktiven
#include "f1.h"
und#include "f2.h"
, und die für diese Direktiven gefundenen Dateien enthalten beide Direktiven#include "f3.h"
. Wennf1.h
undf2.h
sich in verschiedenen Verzeichnissen befinden, die jedoch durch die Suche nach Include-Pfaden gefunden wurden, ist unklar, welche#include
Anweisungen in diesen Dateien zum Laden derselbenf3.h
oder verschiedener Dateien vorgesehen sind.Noch schlimmer wird es, wenn man die Möglichkeiten von Include-Dateien einschließlich relativer Pfade hinzufügt. In einigen Fällen, in denen Header-Dateien relative Pfade für verschachtelte Include-Anweisungen verwenden und Änderungen an bereitgestellten Header-Dateien vermieden werden sollen, kann es erforderlich sein, eine Header-Datei an mehreren Stellen in der Verzeichnisstruktur eines Projekts zu duplizieren. Obwohl mehrere physische Kopien dieser Headerdatei vorhanden sind, sollten sie semantisch als eine einzelne Datei betrachtet werden.
Wenn die
#pragma once
Direktive zulässt, dass ein Bezeichneronce
mit der Semantik folgt , dass der Compiler die Datei überspringen soll, wenn der Bezeichner mit einer von einer zuvor angetroffenen#pragma once
Direktive übereinstimmt , ist die Semantik eindeutig. Ein Compiler, der erkennen konnte, dass eine#include
Direktive dieselbe#pragma once
Datei mit denselben Tags wie eine frühere lädt, konnte durch Überspringen der Datei ein wenig Zeit sparen, ohne sie erneut zu öffnen, aber eine solche Erkennung wäre semantisch nicht wichtig, da die Datei übersprungen würde, ob oder nicht, der Dateiname wurde als Übereinstimmung erkannt. Es sind mir jedoch keine Compiler bekannt, die auf diese Weise arbeiten. Wenn Sie einen Compiler haben, prüfen Sie, ob eine Datei mit dem Muster übereinstimmt,#ifndef someIdentifier / #define someIdentifier / #endif [for that ifndef] / nothing following
und behandeln Sie so etwas als äquivalent zu obigem#pragma once someIdentifier
ifsomeIdentifier
bleibt definiert, ist im wesentlichen so gut.quelle