2009-02-01 11 views
0

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.C++: la fonction d'en-tête n'est pas liée correctement de la bibliothèque à l'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ée et définie dans un fichier d'en-tête (.h Vector3D). Après la déclaration de classe, je la fonction croisée.

La compilation lib est un fichier, mais quand il se relie à l'épreuve de l'unité exe je reçois cette erreur:

flywindow.obj :error LNK2005: "class Vector3d __cdecl cross(class Vector3d const &,class Vector3d const &)" ([email protected]@[email protected]@[email protected]@Z) already defined in fly.obj 

Toutes les idées?

Merci

Répondre

2

Si vous définissez une fonction libre (pas un membre d'une classe), elle doit être définie 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 rendre la compilation par ceci:

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 n'a pas marqué, il en ligne. Si vous incluez maintenant cet en-tête dans deux fichiers compilés séparément, l'éditeur de liens, en essayant de lier les fichiers objets compilés, va renvoyer une erreur, car il voit alors une fonction croisée définie deux fois.

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

Cependant, il n'est généralement pas judicieux de définir des définitions de fonction dans l'en-tête. Si votre fonction dépend d'autres types que le vecteur (dans votre cas c'est bien IMHO, mais c'est discutable bien sûr - certaines personnes ne l'aiment pas), alors vous devrez inclure les en-têtes pour 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 placeront une seule déclaration de votre fonction dans l'en-tête:

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

Mais définir dans le fichier .cpp qui est compilé séparément. L'inline, bien sûr, devrait ensuite être abandonné.


Permettez-moi d'ajouter une petite liste des définitions et des déclarations, juste pour aider à garder les choses claires sur ce que la déclaration et la définition des moyens 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(); 
+0

en ligne travaillé. Merci – cbrulak

1

L'explication la plus probable est que vous avez le code obtenu (en particulier la définition de croix) dans votre fichier à inclure et votre fichier include est inclus par deux fichiers source, 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 (affirmant que quelque chose existe) sont des choses comme des typedef, des déclarations de classe, des énumérations et ainsi de suite.

Les définitions (donnant un sens à ces choses qui existent) sont des choses comme les fonctions, les définitions de varialble et ainsi de suite.

Votre fonction croix 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é.

Questions connexes