c ++: la función de encabezado no se vincula correctamente desde la biblioteca al exe

StackOverflow https://stackoverflow.com/questions/500182

  •  20-08-2019
  •  | 
  •  

Pregunta

Tengo un archivo de encabezado en una biblioteca (alibrary.lib). La biblioteca es una biblioteca estática (.lib) y se vincula correctamente a exe.

Ahora, tengo una clase: Vector3d.

class Vector3d 
{
    void amethod()
    {
       blah
    }

};

Vector3d cross(const Vector3d &v0, const Vector3d &v1) 
{
      float x,y,z;

      x = v0.y*v1.z-v0.z*v1.y;
      y = v0.z*v1.x-v0.x*v1.z;
      z = v0.x*v1.y-v0.y*v1.x;

     return Vector3d(x,y,z);

}

Vector3d se declara y define en un archivo de encabezado (Vector3d .h). Después de la declaración de clase, yo la función cruzada.

La compilación lib es un archivo, pero cuando se vincula al exe de prueba de la unidad, aparece este error:

 flywindow.obj :error LNK2005: "class Vector3d __cdecl cross(class Vector3d const &,class Vector3d const &)" (?cross@@YA?AVVector3d@@ABV1@0@Z) already defined in fly.obj

¿Alguna idea?

Gracias

¿Fue útil?

Solución

Si define una función libre (no miembro de una clase), debe definirse en un archivo .cpp compilado por separado, o en un encabezado y marcado en línea. Entonces, en su caso, puede escapar haciendo que se compile de esta manera:

inline Vector3d cross(const Vector3d &v0, const Vector3d &v1) {
      float x,y,z;

      x = v0.y*v1.z-v0.z*v1.y;
      y = v0.z*v1.x-v0.x*v1.z;
      z = v0.x*v1.y-v0.y*v1.x;

     return Vector3d(x,y,z);

}

El error se debe a que tiene la definición de la función en el encabezado, pero no la ha marcado en línea. Si ahora incluye ese encabezado en dos archivos que se compilan por separado, el vinculador, al intentar vincular los archivos de objetos compilados, arrojará un error, porque luego ve una función cruzada que se define dos veces.

Funciona sin poner explícitamente en línea las funciones miembro de una clase, porque las funciones miembro que se definen dentro de la definición de clase están implícitamente en línea.

Sin embargo, no es una buena idea generalmente hacer definiciones de funciones en el encabezado. Si su función dependería de otros tipos además del vector (en su caso, está bien en mi humilde opinión, pero es discutible, por supuesto, a algunas personas no les gusta), entonces se le solicitará que incluya los encabezados para esos tipos. Eso hinchará innecesariamente el código que se incluye indirectamente en su encabezado. En cambio, en esos casos solo pondría una declaración de su función dentro del encabezado:

Vector3d cross(const Vector3d &v0, const Vector3d &v1);

Pero defínalo dentro del archivo .cpp que se compila por separado. El en línea, por supuesto, debe ser eliminado.


Permítanme agregar una pequeña lista de definiciones y declaraciones, solo para ayudar a mantener las cosas claras sobre lo que significa declaración y definición para funciones y clases. Tenga en cuenta que cada definición también es una declaración, pero no al revés:

// class _declaration_ of boo
class boo;

// class _definition_ of foo.
class foo {
    // member function _declaration_ of bar
    void bar();

    // member function _definition_ of baz
    void baz() { }
};

// function _definition_ of fuzz
inline void fuzz() { }

// function _declaration_ of fezz
void fezz();

Otros consejos

La explicación más probable es que tiene código (específicamente la definición de cruz) en su archivo de inclusión y su archivo de inclusión está siendo incluido por dos archivos fuente, de ahí la doble definición.

Los archivos de encabezado deben tener declaraciones, no definiciones. Las declaraciones (que dicen que algo existe) son cosas como typedef, declaraciones de clase, enumeraciones, etc.

Las definiciones (que dan sentido a las cosas que existen) son funciones, definiciones variables, etc.

Su función cruzada debe declararse en el archivo de encabezado:

Vector3d cross(const Vector3d &v0, const Vector3d &v1);

pero definido en un archivo fuente separado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top