#include in .h oder .c / .cpp?

118

Wo sollte ich beim Codieren in C oder C ++ die haben #include?

callback.h:

#ifndef _CALLBACK_H_
#define _CALLBACK_H_

#include <sndfile.h>
#include "main.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data);
void on_button_cancel_clicked(GtkButton* button, struct user_data_s* data);

#endif

callback.c:

#include <stdlib.h>
#include <math.h>

#include "config.h"

#include "callback.h"
#include "play.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data) {
  gint page;
  page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->notebook));

  ...

Sollten alle Includes entweder in .h oder .c / .cpp oder in beiden enthalten sein, wie ich es hier getan habe?

Louise
quelle
2
Lassen Sie mich das umdrehen und fragen: Was waren Ihre Kriterien für die Entscheidung, sndfile.h und main.h in callback.h einzufügen?
Owen S.

Antworten:

161

Geben Sie so viel wie möglich in die .cund so wenig wie möglich in die .h. Die Includes in the .csind nur enthalten, wenn diese eine Datei kompiliert wird, aber die Includes für die .hmüssen von jeder Datei enthalten sein, die sie verwendet.

Brendan Long
quelle
6
Stimmt, aber hindert das #ifndef _CALLBACK_H_den Compiler nicht daran, es mehr als einmal zu verarbeiten?
Hytromo
11
@ user9379 Dadurch wird verhindert, dass es mehr als einmal pro .c- oder .cpp-Datei enthalten ist. Jede .c- oder .cpp-Datei wird jedoch im Allgemeinen einzeln erstellt. Dies bedeutet, dass für jede von Ihnen kompilierte .c- oder .cpp-Datei eine .h-Datei erneut analysiert wird.
Brendan Long
2
Ich denke, dass der Hauptgrund, so wenig wie möglich in das zu setzen, darin .hbesteht, in einigen Fällen einen Fehler aufgrund einer Einschlussschleife zu vermeiden. Beispiel: Zwei Klassen benötigen einander für ihre Implementierungen, aber nicht für ihre Deklarationen. Wenn Sie beide Includes in das .cpps einfügen, wird ein Fehler vermieden.
Codoskop
1
Die @ Qu'est-cet'yont ein Grund , warum Sie nicht können bestimmte Dinge in den H - Dateien setzen. In dieser Antwort geht es darum, warum Sie noch weniger setzen sollten.
Brendan Long
@BrendanLong Ich sehe, obwohl es in meinem Sinne nicht wichtig ist, mehrmals denselben Header einzuschließen, wenn Sie die richtigen Makros einfügen, um den Inhalt nur einmal einzuschließen. Daher denke ich, dass noch weniger zu setzen bedeutet, die Wahrscheinlichkeiten zu verringern, um in Zukunft einen Fehler mit Änderungen des Codes zu erhalten.
Codoskop
55

Sie sollten einen Header nur dann in eine andere .h-Datei aufnehmen, wenn Sie auf eine Typdefinition in diesem Header zugreifen müssen. beispielsweise:

#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <stdio.h>

void doStuffWith(FILE *f); // need the definition of FILE from stdio.h

#endif

Wenn Header A von Header B abhängt, wie im obigen Beispiel, sollte Header A Header B direkt enthalten. Versuchen Sie NICHT , Ihre Includes in der .c-Datei zu ordnen, um Abhängigkeiten zu erfüllen (dh einschließlich Header B vor Header A). Das ist ein großer Haufen Sodbrennen, der darauf wartet, passiert zu werden. Ich meine es so. Ich war schon mehrere Male in diesem Film und er endete immer mit Tokio in Flammen.

Ja, dies kann dazu führen, dass Dateien mehrmals eingeschlossen werden. Wenn jedoch geeignete Include-Schutzvorrichtungen zum Schutz vor mehreren Deklarations- / Definitionsfehlern eingerichtet sind, sollten Sie sich keine Gedanken über einige zusätzliche Sekunden Erstellungszeit machen. Der Versuch, Abhängigkeiten manuell zu verwalten, ist eine Qual.

Natürlich sollten Sie keine Dateien einfügen, die Sie nicht benötigen .

John Bode
quelle
10

Fügen Sie so viele Includes wie möglich in Ihre CPP ein und nur diejenigen, die von der HPP-Datei in der HPP benötigt werden. Ich glaube, dies wird dazu beitragen, die Kompilierung zu beschleunigen, da HPP-Dateien weniger referenziert werden.

Erwägen Sie auch die Verwendung von Forward-Deklarationen in Ihrer HPP-Datei, um die Include-Abhängigkeitskette weiter zu reduzieren.

Parappa
quelle
1
Oo. Die Sache mit den Vorwärtserklärungen ist interessant.
Brendan Long
Parappa-Forward-Deklarationen sind in Zirkelreferenzszenarien sehr nützlich. Aber wären sie in anderen Szenarien eine gute Praxis? (Ich bin neu in C ++, also
frage
5

Wenn #include <callback.h>ja, möchte ich nicht #includeviele andere Header-Dateien benötigen , um meinen Code kompilieren zu können. In callback.hsollten Sie alles enthalten, was zum Kompilieren erforderlich ist. Aber nichts weiter.

Überlegen Sie, ob mit Vorwärtsdeklarationen in Ihrer Header - Datei (wie class GtkButton;genügt), so dass Sie die Anzahl der reduzieren #includeRichtlinien im Header (und wiederum meine Kompilierung und Komplexität).

Johnsyweb
quelle
Ich bin nicht einverstanden. Das Einbeziehen der ganzen Welt in H-Dateien erhöht die Abhängigkeitskette und damit die Kompilierungszeiten.
John Dibling
In meiner Antwort wurde nicht empfohlen, die ganze Welt in die Header-Datei aufzunehmen. Ich schlug vor, nur so viel aufzunehmen, dass der Benutzer der API keine Zeit damit verbringen muss, nach Abhängigkeiten zu suchen.
Johnsyweb