静的メソッドに関するC ++リンカーの問題
-
06-07-2019 - |
質問
VectorMathクラスの静的メソッドを呼び出して計算を実行するVector3Dクラスを書いています。コンパイルすると、次のようになります:
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) {
しかし、それでも助けにはなりません...
解決
これがありません:
//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());
}
ポインターなし、リークなし、すべてセクシー。
他のヒント
VectorMath.cpp
で Vector3D :: norm
メソッドを定義していません。代わりに、 norm
という名前のグローバル関数を定義しました。あなたがする必要があるのは、定義でメソッド名を修飾することです:
Vector3D* Vector3D::norm(Vector3D* vector)
Vector3D* VectorMath::norm(Vector3D* vector) { // can't be found by linker
// do vector calculations
return new Vector3D(xHead, yHead, zHead, xTail, yTail, zTail);
}