Domanda

Ho un file header in una libreria (alibrary.lib). La libreria è una libreria statica (.lib) e si collega correttamente a exe.

Ora ho una 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 è dichiarato e definito in un file di intestazione (Vector3d .h). Dopo la dichiarazione di classe, ho la funzione croce.

La compilazione lib è un file, ma quando si collega all'ex test unit ho questo errore:

 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

Qualche idea?

Grazie

È stato utile?

Soluzione

Se si definisce una funzione libera (non un membro di una classe), deve essere definita in un file .cpp compilato separatamente, oppure in un'intestazione e contrassegnato in linea. Quindi nel tuo caso, puoi scappare facendolo compilare in questo modo:

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'errore è causato perché hai la definizione della funzione nell'intestazione, ma non l'hai contrassegnata in linea. Se ora includi quell'intestazione in due file che vengono compilati separatamente, il linker, quando tenta di collegare i file oggetto compilati, genererà un errore, poiché vede una funzione incrociata che viene definita due volte.

Funziona senza mettere esplicitamente inline le funzioni membro di una classe, perché le funzioni membro definite nella definizione della classe sono implicitamente in linea.

Non è comunque una buona idea fare delle definizioni di funzione nell'intestazione. Se la tua funzione dipendesse da altri tipi oltre al vettore (nel tuo caso va bene IMHO, ma ovviamente è discutibile - ad alcune persone non piace), allora ti verrà richiesto di includere le intestazioni per quei tipi. Ciò gonfia inutilmente il codice che è indirettamente incluso nella tua intestazione. Invece, in quei casi inseriresti solo una dichiarazione della tua funzione nell'intestazione:

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

Ma definiscilo nel file .cpp compilato separatamente. L'inline, ovviamente, dovrebbe quindi essere abbandonato.


Permettetemi di aggiungere un piccolo elenco di definizioni e dichiarazioni, solo per aiutare a mantenere le cose chiare su ciò che la dichiarazione e la definizione significano per funzioni e classi. Nota che ogni definizione è anche una dichiarazione, ma non viceversa:

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

Altri suggerimenti

La spiegazione più probabile è che hai del codice (in particolare la definizione di cross) nel tuo file include e il tuo file include viene incluso da due file sorgente, da cui la doppia definizione.

I file di intestazione devono contenere dichiarazioni, non definizioni. Le dichiarazioni (intuendo che esiste qualcosa) sono cose come typedef, dichiarazioni di classe, enum e così via.

Le definizioni (dando significato a queste cose che esistono) sono cose come funzioni, definizioni variabili e così via.

La tua funzione incrociata deve essere dichiarata nel file di intestazione:

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

ma definito in un file sorgente separato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top