Soll ich die Includes in die Header-Datei oder in die Quelldatei einfügen? Wenn die Header-Datei die Include-Anweisungen enthält und ich diese Header-Datei dann in meinen Quellcode einfüge, enthält meine Quelldatei dann alle enthaltenen Dateien, die in meinem Header enthalten waren? Oder sollte ich sie nur in meine Quelldatei aufnehmen?
Wo sollen Include-Anweisungen, Header oder Quelle platziert werden?
Mohit Deshpande
schott
Fügen Sie Includes nur dann in einen Header ein, wenn der Header selbst sie benötigt.
Beispiele:
- Ihre Funktion gibt Typ zurück
size_t
. Dann#include <stddef.h>
in dem Header Datei. - Ihre Funktion verwendet
strlen
. Dann#include <string.h>
in dem Quelle Datei.
-
Was ist, wenn meine Funktion ein Argument vom Typ akzeptiert?
size_t
?– andrybak
15. November 2013 um 13:27 Uhr
-
Dieselbe Frage erweitert auf c++: Was ist, wenn meine Struktur/Klasse ein Feld/Member vom Typ hat?
size_t
oderstd::string
?– andrybak
15. November 2013 um 13:32 Uhr
-
Was ist die Begründung?
– Patrizio Bertoni
15. Januar 2016 um 12:51 Uhr
-
Ich habe eine verdrahtete Situation, die C++-Klasse A hat ein Objekt einer anderen Klasse B, und ich kann die Vorwärtsdeklaration von B und das Ende einschließlich des B-Headers innerhalb des A-Headers nicht verwenden. (Die Verwendung des Zeigers hat dieses Problem nicht)
– KRoy
30. August 2017 um 14:49 Uhr
-
@andrybak Ihre Quelldateien sollten Ihre Header-Datei enthalten, damit alle Einschlüsse, die Ihr Header enthält, auch Ihre Quelle erhalten.
– Jeremy Trifilo
9. Januar 2019 um 3:14 Uhr
Darüber gab es im Laufe der Jahre einige Meinungsverschiedenheiten. Früher war es Tradition, dass ein Kopfball nur Deklarieren Sie, was in dem Modul war, auf das es sich bezieht, also viele Kopfzeilen hatte spezifische Anforderungen, die Sie #include
eine bestimmte Gruppe von Headern (in einer bestimmten Reihenfolge). Einige extrem traditionelle C-Programmierer folgen immer noch diesem Modell (religiös, zumindest in einigen Fällen).
In jüngerer Zeit gibt es eine Bewegung dahingehend, die meisten Header eigenständig zu machen. Wenn dieser Header etwas anderes erfordert, kümmert sich der Header selbst darum und stellt sicher, dass alles, was benötigt wird, enthalten ist (in der richtigen Reihenfolge, wenn es Probleme bei der Reihenfolge gibt). Persönlich bevorzuge ich dies – besonders wenn die Reihenfolge der Überschriften wichtig sein kann, löst es das Problem einmal, anstatt dass jeder, der es verwendet, das Problem noch einmal lösen muss.
Beachten Sie, dass die meisten Header nur Deklarationen enthalten sollten. Das bedeutet, dass das Hinzufügen eines unnötigen Headers (normalerweise) keine Auswirkungen auf Ihre endgültige ausführbare Datei haben sollte. Das Schlimmste, was passiert, ist, dass es die Kompilierung etwas verlangsamt.
-
Wenn alle Header im zweiten Stil geschrieben sind, sollte es überhaupt keine Sortierprobleme geben. Bestellprobleme in den Kopfzeilen bedeuten normalerweise, dass Sie nicht alles, was Sie brauchen, in die Kopfzeile aufgenommen haben.
– Kami Kaze
18. Juli 2019 um 14:14 Uhr
Dein #include
s sollten Header-Dateien sein, und jede Datei (Quelle oder Header) sollte #include
die benötigten Header-Dateien. Header-Dateien sollten #include
die minimal erforderlichen Header-Dateien, und Quelldateien sollten dies auch tun, obwohl dies für Quelldateien nicht so wichtig ist.
Die Quelldatei enthält die Header it #include
s, und die Überschriften sie #include
, usw. bis zur maximalen Verschachtelungstiefe. Deshalb wollen Sie nichts Überflüssiges #include
s in Header-Dateien: Sie können dazu führen, dass eine Quelldatei viele Header-Dateien enthält, die sie möglicherweise nicht benötigt, wodurch die Kompilierung verlangsamt wird.
Das bedeutet, dass es durchaus möglich ist, dass Header-Dateien doppelt eingebunden werden, was ein Problem darstellen kann. Die traditionelle Methode besteht darin, “Wächter einzuschließen” in Header-Dateien einzufügen, wie z. B. diese für die Datei foo.h:
#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
/* everything in header goes here */
#endif
-
Ich weiß, dass diese Antwort super alt ist, aber seitdem haben sie #pragma einmal hinzugefügt, also müssen Sie #ifndef nicht einschließen, wenn Sie #includes deklarieren
– Dogunbound-Hunde
13. Januar 2020 um 20:11 Uhr
Der Ansatz, zu dem ich mich in über zwanzig Jahren entwickelt habe, ist folgender;
Betrachten Sie eine Bibliothek.
Es gibt mehrere C-Dateien, eine interne H-Datei und eine externe H-Datei. Die C-Dateien enthalten die interne H-Datei. Die interne H-Datei enthält die externe H-Datei.
Sie sehen, dass es beim Compiler POV eine Hierarchie gibt, wenn er eine C-Datei kompiliert;
extern -> intern -> C-Code
Dies ist die richtige Reihenfolge, da das, was extern ist, alles ist, was ein Dritter benötigt, um die Bibliothek zu benutzen. Das, was intern ist, wird benötigt, um den C-Code zu kompilieren.
Wenn Header-Datei A #includes
Header-Dateien B und C, dann jede Quelldatei, die #includes
A bekommt auch B und C #included
. Der Präprozessor führt buchstäblich nur eine Textersetzung durch: Überall dort, wo er Text findet, der sagt #include <foo.h>
es ersetzt es durch den Text von foo.h
Datei.
Es gibt unterschiedliche Meinungen darüber, ob Sie setzen sollten #includes
in Headern oder Quelldateien. Ich persönlich ziehe es vor, alle zu setzen #includes
standardmäßig in der Quelldatei, aber alle Header-Dateien, die nicht ohne andere erforderliche Header kompiliert werden können, sollten dies tun #include
diese Header selbst.
Und jede Header-Datei sollte einen Include-Guard enthalten, um zu verhindern, dass sie mehrfach eingebunden wird.
Wiederholung
Machen Sie alle Ihre Dateien so, dass sie nur mit dem erstellt werden können, was sie enthalten. Wenn Sie kein Include in Ihrem Header benötigen, entfernen Sie es. Wenn Sie diese Disziplin in einem großen Projekt nicht einhalten, riskieren Sie, einen ganzen Build zu beschädigen, wenn jemand ein Include aus einer Header-Datei entfernt, die von einem Verbraucher dieser Datei und nicht einmal vom Header verwendet wird.
Superkatze
In manchen Umgebungen geht die Kompilierung am schnellsten, wenn man nur die benötigten Header-Dateien einbindet. In anderen Umgebungen wird die Kompilierung optimiert, wenn alle Quelldateien dieselbe primäre Sammlung von Headern verwenden können (einige Dateien haben möglicherweise zusätzliche Header über die gemeinsame Teilmenge hinaus). Idealerweise sollten Header so konstruiert werden, dass mehrere #include-Operationen keine Auswirkung haben. Es kann sinnvoll sein, #include-Anweisungen mit Prüfungen für den include-guard der einzuschließenden Datei zu umgeben, obwohl dies eine Abhängigkeit vom Format dieses Guards erzeugt. Darüber hinaus kann es je nach Datei-Caching-Verhalten eines Systems nicht lange dauern, bis ein unnötiges #include, dessen Ziel vollständig #ifdef’ed ist, nicht lange dauert.
Eine andere zu berücksichtigende Sache ist, dass man den Prototyp schreiben kann, wenn eine Funktion einen Zeiger auf eine Struktur nimmt
void foo(struct BAR_s *bar);
ohne dass eine Definition für BAR_s im Geltungsbereich liegen muss. Ein sehr praktischer Ansatz, um unnötige Includes zu vermeiden.
PS–in vielen meiner Projekte wird es eine Datei geben, von der erwartet wird, dass jedes Modul #include wird, die Dinge wie Typedefs für Integer-Größen und ein paar gemeinsame Strukturen und Vereinigungen enthält[zB[eg
typedef union { unsigned long l; unsigned short lw[2]; unsigned char lb[4]; } U_QUAD;
(Ja, ich weiß, dass ich in Schwierigkeiten geraten würde, wenn ich zu einer Big-Endian-Architektur wechseln würde, aber da mein Compiler keine anonymen Strukturen in Vereinigungen zulässt, würde die Verwendung von benannten Bezeichnern für die Bytes innerhalb der Vereinigung erfordern, dass auf sie zugegriffen wird als theUnion.b.b1 usw., was ziemlich nervig erscheint.
Viele frühere Duplikate auf SO, z. B. wo sollte “include” in C++ eingefügt werden
– PaulR
15. Oktober 2010 um 15:09 Uhr
mögliches Duplikat von Soll ich #include in Headern verwenden?
– schott
15. Oktober 2010 um 15:17 Uhr