c ++: la fonction d'en-tête n'est pas liée correctement d'une bibliothèque à une autre

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

  •  20-08-2019
  •  | 
  •  

Question

J'ai un fichier d'en-tête dans une bibliothèque (alibrary.lib). La bibliothèque est une bibliothèque statique (.lib) et elle est liée correctement à exe.

Maintenant, j'ai une classe: 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 est déclaré et défini dans un fichier d’en-tête (Vector3d .h). Après la déclaration de classe, je remplis la fonction.

La bibliothèque compile est un fichier, mais quand elle est liée à l'exe de test d'unité, l'erreur suivante apparaît:

 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

Des idées?

Merci

Était-ce utile?

La solution

Si vous définissez une fonction libre (pas membre d'une classe), vous devez la définir dans un fichier .cpp compilé séparément, ou dans un en-tête et marqué en ligne. Donc, dans votre cas, vous pouvez vous échapper en le compilant ainsi:

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

}

L'erreur est due au fait que vous avez la définition de la fonction dans l'en-tête, mais que vous ne l'avez pas marquée en ligne. Si vous incluez maintenant cet en-tête dans deux fichiers compilés séparément, l'éditeur de liens, lorsqu'il tente de lier les fichiers d'objet compilés, génère une erreur car il voit alors une fonction transversale être définie deux fois.

Cela fonctionne sans mettre explicitement en ligne pour les fonctions membres d'une classe, car les fonctions membres définies dans la définition de la classe sont implicitement en ligne.

Cependant, ce n’est pas une bonne idée de faire des définitions de fonctions dans l’en-tête. Si votre fonction dépend de types autres que le seul vecteur (dans votre cas, il fonctionne bien, mais c'est discutable bien sûr - certaines personnes ne l'aiment pas), vous devrez alors inclure les en-têtes correspondant à ces types. Cela va inutilement gonfler le code qui est indirectement inclus par votre en-tête. Au lieu de cela, dans ces cas, vous ne mettriez qu'une déclaration de votre fonction dans l'en-tête:

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

Mais définissez-le dans le fichier .cpp compilé séparément. L'inline, bien sûr, devrait alors être abandonné.

Permettez-moi d’ajouter une petite liste de définitions et de déclarations, afin d’aider à clarifier les notions de déclaration et de définition pour les fonctions et les classes. Notez que chaque définition est également une déclaration, mais pas l'inverse:

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

Autres conseils

L'explication la plus probable est que vous avez du code (en particulier la définition de cross) dans votre fichier d'inclusion et que celui-ci est inclus par deux fichiers sources, d'où la double définition.

Les fichiers d'en-tête doivent contenir des déclarations et non des définitions. Les déclarations (indiquant que quelque chose existe) sont des choses telles que celles de typedef, déclarations de classe, enum, etc.

Les définitions (qui donnent un sens à ce qui existe) sont des fonctions telles que des fonctions, des définitions variées, etc.

Votre fonction transversale doit être déclarée dans le fichier d'en-tête:

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

mais défini dans un fichier source séparé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top