Sollte jede C- oder C++-Datei eine zugehörige Header-Datei haben?

Lesezeit: 6 Minuten

Benutzer-Avatar
Vicky

Sollte jede .C- oder .cpp-Datei eine Header-Datei (.h) dafür haben?

Angenommen, es gibt folgende C-Dateien:

  1. Haupt c

  2. Funktion1.C

  3. Funktion2.C

  4. Func3.C

wo main() befindet sich in der Main.C-Datei. Sollte es vier Header-Dateien geben

  1. Main.h

  2. Funktion1.h

  3. Func2.h

  4. Func3.h

Oder soll es nur eine Header-Datei für alle .C-Dateien geben?

Was ist ein besserer Ansatz?

Benutzer-Avatar
paxdiablo

Zunächst einmal wäre es ungewöhnlich, eine zu haben main.h da es normalerweise nichts gibt, was den anderen Kompilierungseinheiten zur Kompilierzeit offengelegt werden muss. Das main() Funktion selbst müssen für den Linker oder den Startcode verfügbar gemacht werden, verwenden jedoch keine Header-Dateien.

Sie können entweder eine Header-Datei pro C-Datei haben oder meiner Meinung nach eher eine Header-Datei für eine verwandte Gruppe von C-Dateien.

Ein Beispiel dafür ist, wenn Sie eine BTree-Implementierung haben und add, delete, search usw. in ihre eigenen C-Dateien eingefügt haben, um die Neukompilierung zu minimieren, wenn sich der Code ändert.

Es macht in diesem Fall keinen Sinn, separate Header-Dateien für jede C-Datei zu haben, da der Header die API ist. Mit anderen Worten, es ist die Ansicht der Bibliothek, wie sie vom Benutzer gesehen wird. Leute, die Ihren Code verwenden, kümmern sich im Allgemeinen sehr wenig darum, wie Sie Ihren Quellcode strukturiert haben, sie möchten nur so wenig Code wie möglich schreiben können, um ihn zu verwenden.

Wenn Sie sie zwingen, mehrere unterschiedliche Header-Dateien einzuschließen, nur damit sie einen Baum erstellen, einfügen, löschen und durchsuchen können, werden sie wahrscheinlich Ihren Verstand in Frage stellen 🙂

Mit wärst du besser dran eines btree.h Datei und eine einzelne btree.lib Datei, die alle BTree-Objektdateien enthält, die aus den einzelnen C-Dateien erstellt wurden.


Ein weiteres Beispiel findet sich in den Standard-C-Headern.

Wir wissen nicht genau, ob es mehrere C-Dateien für alle gibt stdio.h Funktionen (so würde ich es machen, aber es ist nicht die einzige Möglichkeit), aber selbst wenn es welche gäbe, werden sie in Bezug auf die API als Einheit behandelt.

Sie müssen nicht einschließen stdio_printf.h, stdio_fgets.h und so weiter – es gibt eine einzige stdio.h für den Standard-E/A-Teil der C-Laufzeitbibliothek.

  • Keine +1 von mir, da Sie Vorlagen nicht erwähnt haben 🙁

    – Marcin

    4. März 2009 um 22:46 Uhr

  • Ich habe mich mehr auf die C-Seite konzentriert, aber warum sollte ich Templates erwähnen, sogar für C++? Ich sehe ihre Anwendbarkeit nicht auf die verwendeten Header-Dateien (sie können in Header-Dateien gehen, aber auch Typedefs, und ich erwähne sie nicht Sie ausdrücklich).

    – paxdiablo

    4. März 2009 um 22:57 Uhr

  1. Header-Dateien sind nicht obligatorisch.

  2. #include Kopieren Sie einfach die enthaltene Datei (einschließlich .c-Quelldateien) und fügen Sie sie ein.

  3. In realen Projekten werden häufig globale Header-Dateien wie config.h und constants.h die häufig verwendete Informationen enthält, z. B. Flags zur Kompilierzeit und projektweite Konstanten.

  4. Ein gutes Design einer Bibliotheks-API wäre, eine offizielle Schnittstelle mit einem Satz von Header-Dateien bereitzustellen und einen internen Satz von Header-Dateien für die Implementierung mit allen Details zu verwenden. Dies fügt einer C-Bibliothek eine schöne zusätzliche Abstraktionsebene hinzu, ohne unnötige Aufblähung hinzuzufügen.

  5. Verwenden Sie den gesunden Menschenverstand. C/C++ ist nicht wirklich für diejenigen ohne es.

Früher bin ich dem „es kommt darauf an“-Trend gefolgt, bis mir klar wurde, dass Konsistenz, Einheitlichkeit und Einfachheit wichtiger sind, als sich den Aufwand zum Erstellen einer Datei zu sparen, und dass „Standards gut sind, auch wenn sie schlecht sind“.

Was ich meine, ist Folgendes: Ein .cpp/.h-Dateipaar ist so ziemlich das, was alle “Module” sowieso enden. Das Vorhandensein von beidem zu einer Anforderung zu machen, erspart viel Verwirrung und schlechtes Engineering.

Wenn ich zum Beispiel eine Schnittstelle von etwas in einer Header-Datei sehe, weiß ich genau, wo ich nach ihrer Implementierung suchen/platzieren muss. Umgekehrt, wenn ich die Schnittstelle von etwas offenlegen muss, das zuvor in der .cpp-Datei verborgen war (z. B. eine statische Funktion, die global wird), weiß ich genau, wo ich sie platzieren muss.

Ich habe zu viele schlimme Folgen von gesehen nicht nach dieser einfachen Regel. Unnötige Inline-Funktionen, Verstöße gegen jegliche Art von Regeln zur Kapselung, (Nicht-)Trennung von Schnittstelle und Implementierung, falsch platzierter Code, um nur einige zu nennen – alles aufgrund der Tatsache, dass der entsprechende gleichgeordnete Header oder die cpp-Datei nie hinzugefügt wurde.

Also: Definiere immer sowohl .h- als auch .c-Dateien. Machen Sie es zu einem Standard, befolgen Sie es und sicher vertrauen darauf. Das Leben ist auf diese Weise viel einfacher und einfacher ist das Wichtigste in der Software.

  • Das ist dumm. Einige Dinge müssen nicht implementiert werden (zB Konfigurations-Header und so weiter). Code-Standards sind gut, ja, aber sie streng zu befolgen, selbst wenn sie dich eindeutig dazu bringen, etwas Dummes zu tun (wie etwa empty .c Dateien) nicht. Zum Beispiel habe ich in meiner Bibliothek im Moment 52 Header und nur 47 Implementierungsdateien.

    – Thomas

    23. Juli 2013 um 4:29 Uhr


Im Allgemeinen ist es am besten, eine Header-Datei für jede .c-Datei zu haben, die die Deklarationen für Funktionen usw. in der .c-Datei enthält, die Sie verfügbar machen möchten. Auf diese Weise kann eine andere .c-Datei die .h-Datei für die benötigten Funktionen enthalten und muss nicht neu kompiliert werden, wenn eine nicht enthaltene Header-Datei geändert wurde.

Im Allgemeinen gibt es eine .h-Datei für jede .c/.cpp-Datei.

Benutzer-Avatar
jmucchiello

Es hängt davon ab, ob. Normalerweise bestimmt Ihr Grund für separate .c-Dateien, ob Sie separate .h-Dateien benötigen.

Benutzer-Avatar
deworde

Es geht darum, welcher Code welchen anderen Code kennen muss. Sie möchten die Menge, die anderen Dateien bekannt ist, auf das absolute Minimum reduzieren, damit sie ihre Arbeit erledigen können.

Sie müssen wissen, dass eine Funktion existiert, welche Typen sie übergeben müssen und welche Typen sie zurückgeben wird, aber nicht, was sie intern macht. Beachten Sie, dass es aus Sicht des Programmierers auch wichtig ist zu wissen, was diese Typen tatsächlich bedeuten. (z. B. welches int die Zeile und welches die Spalte ist), aber der Code selbst kümmert sich nicht darum. Deshalb lohnt es sich, Funktion und Parameter sinnvoll zu benennen.

Wie andere gesagt haben, wenn es nichts in einer cpp-Datei gibt, das es wert ist, anderen Teilen des Codes ausgesetzt zu werden, wie es normalerweise bei main.c der Fall ist, dann besteht keine Notwendigkeit für eine Header-Datei.

Gelegentlich lohnt es sich, alles, was Sie anzeigen möchten, in eine einzige Header-Datei zu packen (z. B. Func1and2and3.h), damit jeder, der über Func1 Bescheid weiß, auch über Func2 Bescheid weiß, aber ich persönlich bin nicht sehr daran interessiert, da es bedeutet, dass Sie es tun neigen dazu, eine Menge Müll zusammen mit dem Zeug zu laden, das Sie eigentlich wollen.

Zusammenfassung:
Stellen Sie sich vor, Sie vertrauen darauf, dass jemand Code schreiben kann und dass seine Algorithmen, sein Design usw. gut sind. Sie möchten Code verwenden, den sie geschrieben haben. Alles, was Sie wissen müssen, ist, was Sie ihnen geben müssen, um etwas zu bewirken, wofür Sie es geben sollten und was Sie zurückbekommen. Das muss in die Header-Dateien kommen.

1145440cookie-checkSollte jede C- oder C++-Datei eine zugehörige Header-Datei haben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy