2010-06-08 12 views
71

Al codificar en C o C++, ¿dónde debería tener el #include?#include in .h o .c/.cpp?

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

    ... 

caso incluye a todos estar en cualquiera de los .h o .c/.cpp, o ambos, como he hecho aquí?

+2

Déjeme cambiar esto y preguntar: ¿cuál fue su criterio para decidir poner sndfile.hy main.h en callback.h? –

Respuesta

98

Ponga todo lo que pueda en el .c y lo menos posible en el .h. Las inclusiones en .c solo se incluyen cuando se compila ese archivo, pero las inclusiones para el .h tienen que incluirse en cada archivo que lo usa.

+4

Es cierto, pero ¿el '#ifndef _CALLBACK_H_', en la parte superior de la misma, impide que el compilador lo procese más de una vez? – hakermania

+8

@ user9379 Eso evitará que se incluya más de una vez por archivo .c o .cpp. Cada archivo .c o .cpp generalmente se crea individualmente, lo que significa que se volverá a analizar .h por cada archivo .c o .cpp que compile. –

+0

Creo que la razón principal para poner lo menos posible en el '.h' es evitar en algunos casos un error debido a un bucle de inclusión.Ejemplo: dos clases se necesitan mutuamente para sus implementaciones, pero no para sus declaraciones. Poner ambos incluidos en el '.cpp's evitará un error. – Codoscope

5

Si yo #include <callback.h>, no quiero tener que #include muchos otros archivos de encabezado para obtener mi código para compilar. En callback.h debe incluir todo lo necesario para compilar en su contra. Pero nada más.

considerar si utilizando adelante de declaraciones en el archivo de cabecera (como class GtkButton;) será suficiente, lo que permite reducir el número de #include directivas en la cabecera (y, a su vez, mi tiempo de compilación y complejidad).

+0

No estoy de acuerdo. Incluir todo el mundo en archivos H aumenta la cadena de dependencias y, por lo tanto, compila los tiempos. –

+0

Mi respuesta no recomienda incluir todo el mundo en el archivo de encabezado, sugerí incluir * solo * suficiente para que el usuario de la API no tenga que perder tiempo buscando dependencias. – Johnsyweb

8

Ponga tantas como sea posible en su cpp como sea posible y solo las que necesita el archivo hpp en la hpp. Creo que esto ayudará a acelerar la compilación, ya que los archivos hpp tendrán una referencia cruzada menor.

También considere usar forward declarations en su archivo hpp para reducir aún más la cadena de dependencia de incluir.

+0

Oo. Lo de las declaraciones avanzadas es interesante. –

+0

Parappa, las declaraciones avanzadas son muy útiles en escenarios de referencia circulares. Pero, ¿serían una buena práctica en otros escenarios? (Soy nuevo en C++, así que honestamente estoy preguntando) – Dzyann

28

La única vez que debe incluir un encabezado dentro de otro archivo .h es si necesita acceder a una definición de tipo en ese encabezado; por ejemplo:

#ifndef MY_HEADER_H 
#define MY_HEADER_H 

#include <stdio.h> 

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

#endif 

Si el encabezado A depende del encabezado B como en el ejemplo anterior, el encabezado A debe incluir el encabezado B directamente. Do NOT intente ordenar sus inclusiones en el archivo .c para satisfacer las dependencias (es decir, incluyendo el encabezado B antes del encabezado A); esa es una gran pila de acidez estomacal esperando a suceder. Lo digo en serio. He estado en esa película varias veces, y siempre terminó con Tokio en llamas.

Sí, esto puede hacer que los archivos se incluyan varias veces, pero si tienen protectores de inclusión adecuados configurados para proteger contra múltiples errores de declaración/definición, entonces algunos segundos extra de tiempo de compilación no valen la pena preocuparse. Tratar de administrar las dependencias manualmente es un dolor de cabeza.

Por supuesto, no debe incluir archivos en los que no necesita para.