Проблемы с компоновщиком в C ++ со статическим методом - PullRequest
4 голосов
/ 31 июля 2009

Я пишу класс Vector3D, который вызывает статический метод класса VectorMath для выполнения вычислений. Когда я компилирую, я получаю это:

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

код:

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
}        

Почему компоновщик не может найти метод VectorMath::norm? На первый взгляд, я думаю, что мне нужно объявить норму следующим образом:

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

но это тоже не помогает ...

Ответы [ 3 ]

15 голосов
/ 31 июля 2009

Вам не хватает этого:

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

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

Функция norm является частью VectorMath::. Без этого у вас просто есть бесплатная функция.


Это больше касается вашего дизайна, но почему вы используете указатели на все? Это намного чище:

class VectorMath {
    public:
    static Vector3D norm(const Vector3D&);
};

Возьмите ссылки, вы на C ++, поэтому не пишите код на C. Что происходит, когда я это называю?

VectorMath::norm(0); // null

Это может произойти сбой, вы должны поставить чек, в случае чего, что он должен вернуть? Это все очищено с помощью ссылок.

Кроме того, почему бы просто не сделать этих членов Vector3D класса?

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

И наконец, вещи, выделяемые стеком. У вашего кода сейчас утечка памяти:

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

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

Измените его на это и используйте RAII понятия:

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

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

И, сделав norm функцией-членом, вы получите очень чистый код:

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

Нет указателей, нет утечек, все сексуально.

4 голосов
/ 31 июля 2009

Вы не определили метод Vector3D::norm в VectorMath.cpp. Вместо этого вы определили глобальную функцию с именем norm. Что вам нужно сделать, это указать название метода в определении:

Vector3D* Vector3D::norm(Vector3D* vector)
0 голосов
/ 31 июля 2009
Vector3D* VectorMath::norm(Vector3D* vector) { // can't be found by linker
    // do vector calculations
    return new Vector3D(xHead, yHead, zHead, xTail, yTail, zTail);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...