2010-09-29 19 views
20

Uno de mis amigos "no programadores" recientemente decidió realizar un programa en C++ para resolver un problema mecánico complicado.Compilación y vinculación de varios archivos en C++

Él escribió cada función en un archivo .cpp separada, a continuación, todos ellos incluidos en el fichero fuente principal, algo como esto:

main.cpp:

#include "function1.cpp" 
#include "function2.cpp" 
... 
int main() 
{ 
... 

} 

Luego compilado el código, con una sola línea de gcc:

g++ main.cpp // took about 2 seconds 

Ahora, sé que este debería funcionar, pero no estoy seguro de si incluir archivos .cpp directamente en el programa principal es una buena idea. He visto el siguiente esquema varias veces, donde todos los prototipos de las funciones van en un fichero de cabecera con la palabra clave extern, así:

funcs.h:

extern void function1(..); 
extern void function2(..); 
... 

main.cpp:

... 
#include "funcs.h" 
... 

& compilar con:

g++ -c function1.cpp 
g++ -c function2.cpp 
... 
g++ -c main.cpp 
g++ -o final main.o function1.o function2.o ... 

Creo que este esquema es mejor (con un archivo MAKE, por supuesto). ¿Qué razones puedo darle a mi amigo para convencerlo así?

+2

Todo termina siendo lo mismo, menos posible algunas optimizaciones de vinculador que no se pueden aplicar a través de 'módulos'. – leppie

+0

@leppie: gcc y msvc tienen opciones de optimización de tiempo de enlace que le permiten al vinculador optimizar en varios "módulos" de archivos de origen. – rubenvb

Respuesta

21

La razón principal por la que las personas compilan objeto por objeto es para ahorrar tiempo. Los cambios de código localizados de alto nivel a menudo solo requieren la compilación de un objeto y una nueva vinculación, que puede ser más rápida. (Compilar demasiados objetos que dibujan montones de encabezados, o crear instancias redundantes de las mismas plantillas, en realidad puede ser más lento cuando un cambio en el código común desencadena una recompilación más completa).

Si el proyecto es tan pequeño que se puede compilar en 2 segundos, no hay mucho beneficio real para el enfoque tradicional, aunque hacer lo que se espera puede ahorrarle tiempo al desarrollador, como el suyo y el nuestro aquí :-). De equilibrio que, manteniendo un makefile toma tiempo también, aunque bien puede terminar haciendo que de todos modos con el fin de capturar convenientemente incluyen directorios, bibliotecas, etc. modificadores del compilador

implicaciones reales a código escrito/generada:

  • Normalmente, los archivos cpp incluyen sus propios encabezados, lo que proporciona una verificación de que el contenido del encabezado puede usarse independientemente por otro código de cliente: junte todo y el espacio de nombres ya está "contaminado" con inclusiones de los primeros encabezados/archivos de implementación
  • el compilador puede optimizar mejor cuando todo está en una unidad de traducción (+1 para el c de Leppie omment, haz lo mismo ...)
  • variables estáticas no miembro y espacios de nombres anónimos son privados para la unidad de traducción, por lo que incluir múltiples cpps significa compartir estos, para bien o para mal (+1 para Alexander :-))
  • decir que los archivos cpp definen una función o variable que no se menciona en su encabezado e incluso podría estar en un espacio de nombres anónimo o estático: el código más adelante en la unidad de traducción podría llamarlo libremente sin necesidad de modificar su propia declaración directa (esto es malo - si la función era intencionada) para ser llamado fuera de su propio cpp, entonces debería haber estado en el encabezado y un símbolo expuesto externamente en el objeto de su unidad de traducción)

BTW - en C++ los encabezados pueden descifrar lare funciones sin utilizar explícitamente la palabra clave extern, y es normal hacerlo.

6

El motivo del segundo estilo es que cada archivo .cpp se puede tratar por separado, con sus propias clases, variables globales, etc. sin riesgo de conflicto.

También es más fácil en los IDE que vinculan automáticamente todos los archivos .cpp (como MSVC).

Cuestiones relacionadas