una todas tipos prototipos las funciones funcion estructura ejemplos codigo clases c++ definition friend

c++ - todas - Error con múltiples definiciones de función



tipos de funciones en c++ (2)

Estoy tratando de volver a aprender C ++ después de tomar un curso introductorio hace unos años y estoy teniendo algunos problemas básicos. Mi problema actual ocurre cuando intento usar una función amiga. Aquí está mi código en 2 archivos.

Primero:

// fun.cpp #include <iostream> using namespace std; class classA { friend void funct(); public: classA(int a=1,int b=2):propa(a),propb(b){cout<<"constructor/n";} private: int propa; int propb; void outfun(){ cout<<"propa="<<propa<<endl<<"propb="<<propb<<endl; } }; void funct(){ // ERROR HERE cout<<"enter funct"<<endl; classA tmp(1,2); tmp.outfun(); cout<<"exit funct"<<endl; }

Segundo:

// mainfile.cpp #include <iostream> #include "fun.cpp" using namespace std; int main(int nargin,char* varargin[]) { cout<<"call funct"<<endl; funct(); cout<<"exit main"<<endl; return 0; }

El error que obtengo es "definición múltiple de` funct () ''". ¿Estoy usando la sintaxis incorrecta cuando la declaro como una función amiga?


Aquí hay una vista muy simplificada, pero con suerte relevante, de lo que sucede cuando construyes tu código en C ++.

C ++ divide la carga del código ejecutable de la máquina en las siguientes fases:

  1. Preprocesamiento : aquí es donde cualquier macros - #define s etc. que pueda estar utilizando se expanda.

  2. Compilación : cada archivo cpp, junto con todos los archivos #include d en ese archivo, directa o indirectamente (en conjunto, se denomina unidad de compilación) se convierte en código de objeto legible por la máquina.

    Aquí es donde C ++ también comprueba que todas las funciones definidas (es decir, que contienen un cuerpo en { } por ejemplo, void Foo( int x){ return Boo(x); }) se refieren a otras funciones de una manera válida.

    La forma de hacerlo es insistiendo en que proporcione al menos una declaración de estas otras funciones (por ejemplo, void Boo(int); ) antes de llamarla para que pueda verificar que la está llamando correctamente, entre otras cosas. Esto se puede hacer directamente en el archivo cpp donde se llama o, por lo general, en un archivo de encabezado incluido.

    Tenga en cuenta que solo el código de máquina que corresponde a las funciones definidas en este cpp y los archivos incluidos se construye como la versión de objeto (binario) de esta unidad de compilación (por ejemplo, Foo) y no los que están simplemente declarados (por ejemplo, Boo).

  3. Enlace : esta es la etapa en la que C ++ sale a buscar cosas declaradas y llamadas en cada unidad de compilación y las vincula a los lugares donde se llama. Ahora bien, si no se ha encontrado una definición de esta función, el enlazador se da por vencido y se equivoca. Del mismo modo, si encuentra varias definiciones de la misma firma de función (esencialmente el nombre y los tipos de parámetros que toma) también se equivoca al considerarla ambigua y no quiere elegir una de forma arbitraria.

Esto último es lo que está sucediendo en tu caso. Al realizar una #include fun.cpp archivo fun.cpp , tanto fun.cpp como mainfile.cpp tienen una definición de funct() y el enlazador no sabe cuál usar en su programa y se queja de ello.

La solución que Vaughn mencionó anteriormente es no incluir el archivo cpp con la definición de funct() en mainfile.cpp y, en su lugar, mover la declaración de funct() en un archivo de encabezado independiente e incluirla en mainline.cpp . De esta manera, el compilador obtendrá la declaración de funct() para trabajar y el enlazador solo obtendrá una definición de funct() de fun.cpp y la usará con confianza.


El problema es que si incluye fun.cpp en dos lugares de su programa, terminará definiéndolo dos veces, lo cual no es válido.

No quieres incluir archivos cpp . Desea incluir archivos de encabezado.

El archivo de encabezado debería tener la definición de clase. El archivo cpp correspondiente, que compilará por separado, tendrá la definición de la función.

fun.hpp:

#include <iostream> class classA { friend void funct(); public: classA(int a=1,int b=2):propa(a),propb(b){std::cout<<"constructor/n";} private: int propa; int propb; void outfun(){ std::cout<<"propa="<<propa<<endl<<"propb="<<propb<< std::endl; } };

fun.cpp:

#include "fun.hpp" using namespace std; void funct(){ cout<<"enter funct"<<endl; classA tmp(1,2); tmp.outfun(); cout<<"exit funct"<<endl; }

mainfile.cpp:

#include <iostream> #include "fun.hpp" using namespace std; int main(int nargin,char* varargin[]) { cout<<"call funct"<<endl; funct(); cout<<"exit main"<<endl; return 0; }

Tenga en cuenta que generalmente se recomienda evitar el using namespace std en los archivos de encabezado.