c++ - descargar - Incluyendo archivos.cpp
c++ manual (8)
He leído en lugares como here que debe incluir archivos .h y no archivos .cpp, porque de lo contrario, obtendrá un error. Así por ejemplo
main.cpp
#include <iostream>
#include "foop.h"
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
foop.h
#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif
foop.cpp
int foo(int a){
return ++a;
}
funciona, pero si reemplazo #include "foop.h"
con #include "foop.cpp"
un error (usando Dev C ++ 4.9.9.2, Windows):
multiple definition of foo(int)
first defined here
¿Por qué es esto?
Cuando dices #include "foop.cpp"
, es como si hubieras copiado todo el contenido de foop.cpp
y lo foop.cpp
pegado en main.cpp
.
Entonces, cuando compila main.cpp
, el compilador emite un main.obj
que contiene el código ejecutable para dos funciones: main
y foo
.
Cuando compila foop.cpp
sí, el compilador emite un foop.obj
que contiene el código ejecutable para la función foo
.
Cuando los vincula, el compilador ve dos definiciones para la función foo
(una de main.obj
y la otra de foop.obj
) y se queja de que tiene múltiples definiciones.
Debido a la regla de una sola definición (probablemente 1 ).
En C ++, cada objeto y función no en línea debe tener exactamente una definición dentro del programa. Al #include
el archivo en el que se define foo(int)
(el archivo CPP), se define tanto en cada archivo donde foop.cpp es #include
d, como en foop.cpp en sí (suponiendo que se compila foop.cpp) .
Puede hacer una función en inline
para anular este comportamiento, pero no lo estoy recomendando aquí. Nunca he visto una situación en la que sea necesario o incluso deseable #include
un archivo CPP.
Hay situaciones en las que es deseable incluir una definición de algo. Esto es especialmente cierto cuando intenta separar la definición de una plantilla de su declaración. En esos casos, nombro el archivo HPP en lugar de CPP para indicar la diferencia.
1 : "(probablemente)" Digo probablemente aquí porque el código real que has publicado debe compilarse sin errores, pero dado el error del compilador, es probable que el código que publicaste no sea exactamente el mismo que el código que estás compilando .
Debido a que su programa ahora contiene dos copias de la función foo
, una vez dentro de foo.cpp y una vez dentro de main.cpp
Piense en #include como una instrucción para el compilador de copiar / pegar el contenido de ese archivo en su código, por lo que terminará con un main.cpp procesado que se parece a esto
#include <iostream> // actually you''ll get the contents of the iostream header here, but I''m not going to include it!
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
y foo.cpp
int foo(int a){
return ++a;
}
de ahí el error de definición múltiple
Esto se reduce a una diferencia entre definiciones y declaraciones .
- Puede declarar funciones y variables varias veces, en diferentes unidades de traducción o en la misma unidad de traducción. Una vez que declaras una función o una variable, puedes usarla desde ese momento.
- Puede definir una función no estática o una variable solo una vez en todas sus unidades de traducción. La definición de elementos no estáticos más de una vez provoca errores de enlazador.
Los encabezados generalmente contienen declaraciones; Los archivos cpp contienen definiciones. Cuando incluye un archivo con definiciones más de una vez, obtiene duplicados durante el enlace.
En su situación, una definición proviene de foo.cpp
, y la otra definición proviene de main.cpp
, que incluye foo.cpp
.
Nota: si cambia foo
para que sea static
, no tendría errores de enlace. A pesar de la falta de errores, esto no es algo bueno que hacer.
Hay muchas razones para desalentar, incluido un archivo .cpp, pero no está estrictamente prohibido. Tu ejemplo debería compilar bien.
El problema probablemente sea que compilas main.cpp y foop.cpp, lo que significa que dos copias de foop.cpp se están vinculando entre sí. El enlazador se queja de la duplicación.
Lo que include
does es copiar todo el contenido del archivo (que es el argumento dentro de <>
o de ""
), por lo que cuando el preprocesador finaliza su trabajo, main.cpp
se verá así:
// iostream stuff
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
Así que foo se definirá en main.cpp
, pero también existe una definición en foop.cpp
, por lo que el compilador "se confunde" debido a la duplicación de funciones.
Solo debe incluir archivos de encabezado.
Si incluye un archivo de encabezado, el archivo de encabezado buscará automáticamente el archivo .cpp. -> Este proceso lo realiza LINKER.
Usar el método ".h" es mejor Pero si realmente quieres incluir el archivo .cpp, haz foo (int) estático en foo.cpp