375 Stimmen

Reihenfolge der C/C++-Include-Header-Dateien

In welcher Reihenfolge sollten Include-Dateien angegeben werden, d.h. was sind die Gründe für die Aufnahme eines Headers vor einem anderen?

Werden zum Beispiel die Systemdateien, STL und Boost vor oder nach den lokalen Include-Dateien eingefügt?

400voto

squelart Punkte 10785

Ich glaube nicht, dass es eine empfohlene Reihenfolge gibt, Hauptsache, es wird kompiliert! Was ärgerlich ist, ist, wenn einige Header erfordern, dass andere Header zuerst eingefügt werden... Das ist ein Problem mit den Headern selbst, nicht mit der Reihenfolge der Includes.

Ich persönlich ziehe es vor, von der lokalen bis zur globalen Ebene zu gehen, jeden Unterabschnitt in alphabetischer Reihenfolge, d.h.:

  1. h-Datei, die zu dieser cpp-Datei gehört (falls zutreffend)
  2. Kopfzeilen aus derselben Komponente,
  3. Kopfzeilen aus anderen Komponenten,
  4. Systemkopfzeilen.

Meine Begründung für 1. ist, dass es beweisen sollte, dass jeder Header (für den es eine cpp gibt) #include d ohne Voraussetzungen (terminus technicus: Header ist "in sich geschlossen"). Und der Rest scheint einfach logisch daraus zu folgen.

163voto

Nathan Paul Simons Punkte 1526

Wichtig ist, dass Ihre Kopfzeilen nicht davon abhängig sind, dass andere Kopfzeilen zuerst eingefügt werden. Eine Möglichkeit, dies zu gewährleisten, besteht darin, Ihre Kopfzeilen vor allen anderen Kopfzeilen einzufügen.

In "Thinking in C++" wird dies besonders erwähnt, wobei auf Lakos' "Large Scale C++ Software Design" verwiesen wird:

Latente Verwendungsfehler können vermieden werden, indem sichergestellt wird, dass die .h-Datei einer Komponente von selbst parst - ohne extern bereitgestellte Deklarationen oder Definitionen... Das Einfügen der .h-Datei als allererste Zeile der .c-Datei stellt sicher, dass keine kritische Information, die für die physische Schnittstelle der Komponente wichtig ist, in der .h-Datei fehlt (oder, falls doch, dass Sie dies herausfinden, sobald Sie versuchen, die .c-Datei zu kompilieren).

Das heißt, sie sollten in der folgenden Reihenfolge aufgenommen werden:

  1. Der Prototyp/Schnittstellen-Header für diese Implementierung (d. h. die .h/.hh-Datei, die dieser .cpp/.cc-Datei entspricht).
  2. Andere Kopfzeilen aus demselben Projekt, je nach Bedarf.
  3. Header von anderen Nicht-Standard-, Nicht-System-Bibliotheken (z. B. Qt, Eigen, etc.).
  4. Kopfzeilen aus anderen "Fast-Standard"-Bibliotheken (z. B. Boost)
  5. Standard-C++-Header (z. B. iostream, functional usw.)
  6. Standard-C-Header (z. B. cstdint, dirent.h, usw.)

Wenn eine der Kopfzeilen ein Problem damit hat, in dieser Reihenfolge aufgeführt zu werden, sollten Sie sie entweder korrigieren (falls vorhanden) oder nicht verwenden. Boykottieren Sie Bibliotheken, die keine sauberen Header schreiben.

Googles C++-Style Guide argumentiert fast die umgekehrte Variante, für die es eigentlich keinerlei Rechtfertigung gibt; ich persönlich neige dazu, den Lakos-Ansatz zu bevorzugen.

53voto

paxdiablo Punkte 809679

Ich befolge zwei einfache Regeln, die die meisten Probleme vermeiden:

  1. Alle Kopfzeilen (und auch jede Quelldateien) sollten das enthalten, was sie brauchen. Sie sollten pas sind darauf angewiesen, dass ihre Nutzer Dinge einschließen.
  2. Außerdem sollten alle Kopfzeilen mit einem Include-Schutz versehen werden, damit sie nicht durch eine übermäßige Anwendung der obigen Regel 1 mehrfach eingeschlossen werden.

Ich befolge auch die Leitlinien von:

  1. Fügen Sie zuerst die Systemheader (stdio.h usw.) mit einer Trennlinie ein.
  2. Gruppieren Sie sie logisch.

Mit anderen Worten:

#include <stdio.h>
#include <string.h>

#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"

Aber da es sich um Leitlinien handelt, ist das eine subjektive Sache. Die Regeln hingegen setze ich rigoros durch, sogar bis zu dem Punkt, dass ich "Wrapper"-Header-Dateien mit Include-Guards und gruppierten Includes zur Verfügung stelle, wenn ein unausstehlicher Drittentwickler sich nicht an meine Vision hält :-)

30voto

Matthieu M. Punkte 266317

Meinen eigenen Ziegelstein zur Mauer hinzufügen.

  1. Jede Kopfzeile muss autark sein, was nur getestet werden kann, wenn sie mindestens einmal enthalten ist
  2. Man sollte die Bedeutung einer fremden Kopfzeile nicht fälschlicherweise durch die Einführung von Symbolen (Makros, Typen usw.) verändern.

Also gehe ich normalerweise so vor:

// myproject/src/example.cpp
#include "myproject/example.h"

#include <algorithm>
#include <set>
#include <vector>

#include <3rdparty/foo.h>
#include <3rdparty/bar.h>

#include "myproject/another.h"
#include "myproject/specific/bla.h"

#include "detail/impl.h"

Jede Gruppe ist durch eine Leerzeile von der nächsten Gruppe getrennt:

  • Header, der dieser cpp-Datei entspricht, zuerst (Plausibilitätsprüfung)
  • System-Kopfzeilen
  • Kopfzeilen von Drittanbietern, geordnet nach der Reihenfolge der Abhängigkeiten
  • Projektüberschriften
  • Private Kopfzeilen des Projekts

Beachten Sie auch, dass sich jede Datei, abgesehen von den Systemheadern, in einem Ordner mit dem Namen ihres Namensraums befindet, weil es auf diese Weise einfacher ist, sie zu finden.

18voto

i_am_jorf Punkte 52346

Ich empfehle:

  1. Der Header für das .cc-Modul, das Sie erstellen. (Dies hilft sicherzustellen, dass jeder Header in Ihrem Projekt keine impliziten Abhängigkeiten von anderen Headern in Ihrem Projekt hat).
  2. C-Systemdateien.
  3. C++-Systemdateien.
  4. Plattform / Betriebssystem / andere Header-Dateien (z.B. win32, gtk, openGL).
  5. Andere Header-Dateien aus Ihrem Projekt.

Und natürlich in alphabetischer Reihenfolge innerhalb der einzelnen Abschnitte, soweit möglich.

Verwenden Sie immer Forward-Deklarationen, um unnötige #include s in Ihren Header-Dateien.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X