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


118

Quando si codifica in C o C ++, dove dovrei avere la #includes?

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));

  ...

Tutti gli include dovrebbero essere in .h o .c / .cpp, o entrambi come ho fatto qui?


2
Permettimi di capovolgere la questione e chiederti: quali sono stati i tuoi criteri per decidere di mettere sndfile.he main.h in callback.h?
Owen S.

Risposte:


161

Metti il ​​più possibile in .ce il meno possibile in .h. Gli include in .csono inclusi solo quando quel file viene compilato, ma gli include per .hdevono essere inclusi in ogni file che lo utilizza.


6
Vero, ma soprattutto non #ifndef _CALLBACK_H_impedisce al compilatore di elaborarlo più di una volta?
hytromo

11
@ user9379 Ciò impedirà che venga incluso più di una volta per file .c o .cpp. Ogni file .c o .cpp viene generalmente creato individualmente, il che significa che un .h verrà rianalizzato per ogni file .c o .cpp che compili.
Brendan Long,

2
Penso che il motivo principale per mettere il meno possibile in the .hsia per evitare in alcuni casi un errore a causa di un ciclo di inclusione. Esempio: due classi hanno bisogno l'una dell'altra per le loro implementazioni, ma non per le loro dichiarazioni. Mettere entrambi gli include nella .cpps eviterà un errore.
Codoscope

1
@ Qu'est-cet'yont Questo è un motivo per cui non puoi mettere certe cose nei file .h. Questa risposta riguarda il motivo per cui dovresti mettere anche meno di quello.
Brendan Long,

@BrendanLong vedo, anche se nel mio senso includere più volte una stessa intestazione non importa se inserisci le macro corrette all'interno per includere il contenuto solo una volta. Pertanto, penso che mettere ancora meno sia ridurre le probabilità di ottenere un errore in futuro con modifiche al codice.
Codoscope

55

L'unica volta che dovresti includere un'intestazione all'interno di un altro file .h è se devi accedere a una definizione di tipo in quell'intestazione; per esempio:

#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <stdio.h>

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

#endif

Se l'intestazione A dipende dall'intestazione B come nell'esempio precedente, l'intestazione A dovrebbe includere direttamente l'intestazione B. Non NON cercare di ordinare il include nel file .c per soddisfare le dipendenze (cioè, tra cui intestazione B prima intestazione A); questo è un grosso mucchio di bruciore di stomaco in attesa di accadere. Voglio dire che. Sono stato in quel film diverse volte e finiva sempre con Tokyo in fiamme.

Sì, questo può comportare che i file vengano inclusi più volte, ma se dispongono di protezioni di inclusione adeguate impostate per proteggere da più errori di dichiarazione / definizione, non vale la pena preoccuparsi di qualche secondo in più di tempo di compilazione. Cercare di gestire manualmente le dipendenze è una seccatura.

Ovviamente, non dovresti includere file in cui non è necessario .


10

Metti il ​​maggior numero possibile di include nel tuo cpp e solo quelli necessari per il file hpp nel file hpp. Credo che questo aiuterà ad accelerare la compilazione, poiché i file hpp avranno meno riferimenti incrociati.

Considera anche l'utilizzo di dichiarazioni anticipate nel tuo file hpp per ridurre ulteriormente la catena di dipendenze include.


1
Oo. La cosa delle dichiarazioni previsionali è interessante.
Brendan Long,

Parappa, le dichiarazioni anticipate sono molto utili negli scenari di riferimento circolare. Ma sarebbero una buona pratica in altri scenari? (Sono nuovo in C ++, quindi sto chiedendo onestamente)
Dzyann

5

Se lo faccio #include <callback.h>, non voglio avere #includemolti altri file di intestazione per compilare il mio codice. In callback.hdovresti includere tutto il necessario per compilare contro di esso. Ma niente di più.

Considera se l'uso di dichiarazioni anticipate nel tuo file di intestazione (come class GtkButton;) sarà sufficiente, permettendoti di ridurre il numero di #includedirettive nell'intestazione (e, a sua volta, il mio tempo di compilazione e complessità).


Non sono d'accordo. Includere l'intero mondo nei file H aumenta la catena delle dipendenze e quindi i tempi di compilazione.
John Dibling

La mia risposta non ha raccomandato tra cui il mondo intero nel file di intestazione, ho proposto di inserire solo sufficiente in modo che l'utente delle API non ha bisogno di spendere tempo alla ricerca di dipendenze.
Johnsyweb
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.