2009-07-31 2 views
4

Ich schreibe eine Vector3D-Klasse, die eine statische Methode für eine VectorMath-Klasse aufruft, um eine Berechnung durchzuführen. Wenn ich kompilieren, bekomme ich diese:C++ - Linker Probleme mit statischen Methode

 
bash-3.1$ g++ VectorMath.cpp Vector3D.cpp 
/tmp/cc5cAPia.o: In function `main': 
Vector3D.cpp:(.text+0x4f7): undefined reference to 'VectorMath::norm(Vector3D*)' 
collect2: ld returned 1 exit status 

Der Code:

VectorMath.h:

#ifndef VECTOR3D_H 
#include "Vector3D.h" 
#endif 

class VectorMath { 
    public: 
    static Vector3D* calculatePerpendicularVector(Vector3D*, Vector3D*); 
    static Vector3D* norm(Vector3D*); 
    static double length(Vector3D*); 
}; 

VectorMath.cpp

#include "VectorMath.h" 
Vector3D* norm(Vector3D* vector) { // can't be found by linker 
    // do vector calculations 
    return new Vector3D(xHead, yHead, zHead, xTail, yTail, zTail); 
} 
// other methods 

Vector3D. cpp

#include "Vector3D.h" 
#include "VectorMath.h" 
// ... 
// vector implementation 
// ... 
int main(void) { 
    Vector3D* v = new Vector3D(x, y, z); 
    Vector3D* normVector = VectorMath::norm(v); // error here 
}   

Warum kann die VectorMath::norm Methode nicht der Linker finden? Auf den ersten Blick würde ich denken, dass ich brauchen würde Norm wie folgt zu erklären:

Vector3D* VectorMath::norm(Vector3D* vector) { 

aber das hilft auch nicht ...

+0

Dies: "aber das hilft auch nicht ..." ist nicht genug Information. Was bedeutet das? Gleiche Fehler, verschiedene Fehler? – GManNickG

Antwort

14

Sie verpassen dies:

//VectorMath.cpp 
#include "VectorMath.h" 

      | 
      V - here 
Vector3D* VectorMath::norm(Vector3D* vector) 
{ 
    ... 
} 

Die norm Funktion Teil VectorMath:: ist. Ohne das haben Sie nur eine kostenlose Funktion.


Dies ist mehr über Ihr Design, aber warum verwenden Sie Zeiger auf alles? Dies ist viel sauberer:

Nehmen Sie Referenzen, Sie sind in C++ also nicht C-Code schreiben. Was passiert, wenn ich das anrufe?

VectorMath::norm(0); // null 

Es wird entweder abstürzen, müssen Sie einen Scheck setzen, wobei in diesem Fall, was soll es zurückgeben? Dies wird alles durch die Verwendung von Referenzen bereinigt.

Auch, warum nicht einfach diese Mitglieder der Vector3D Klasse machen?

Vector3D* v = new Vector3D(x, y, z); 
v->norm(); // normalize would be better, in my opinion 

Schließlich, stapeln Sie die Dinge.Ihr Code Recht hat jetzt ein Speicherleck:

int main(void) { 
    Vector3D* v = new Vector3D(x, y, z); 
    Vector3D* normVector = VectorMath::norm(v); 

    // delete v; 
    //^you're not deleting it! 
}   

ändert sie dazu verwenden, RAII Konzepte:

int main(void) { 
    Vector3D v(x, y, z); 
    Vector3D* normVector = VectorMath::norm(v); 

    // delete v; 
    //^you're not deleting it! 
}  

Und indem norm Mitglied Funktion, die Sie mit dem sehr sauberen Code am Ende:

int main(void) { 
    Vector3D v(x, y, z); 
    Vector3D normVector(v.norm()); 
}  

Keine Hinweise, keine Lecks, alle sexy.

+0

OK, danke, das scheint zu funktionieren. Ich schwöre, dass ich das vorher versucht habe und es gescheitert ist - aber es funktioniert jetzt ... Danke für die Hinweise auf das Memory-Leak-Ding ... Ich schätze, ich werde eine neue Frage über diese stellen ... –

+0

@GMan, Beeindruckende Antwort :) – mahesh

4

Sie haben nicht Vector3D::norm Methode in VectorMath.cpp definiert. Stattdessen haben Sie eine globale Funktion mit dem Namen norm definiert. Was Sie tun müssen, ist die Methodennamen in der Definition qualifizieren:

Vector3D* Vector3D::norm(Vector3D* vector) 
+0

Sie sind 24 Sekunden schneller als ich. : [ – GManNickG

0
Vector3D* VectorMath::norm(Vector3D* vector) { // can't be found by linker 
    // do vector calculations 
    return new Vector3D(xHead, yHead, zHead, xTail, yTail, zTail); 
}