我遇到了一个问题,这很可能是由循环依赖类的错误前向声明引起的。但是向前声明模板类(类似于here似乎仍然无法正常工作。
使用Visual Studio Express Edition 2013我会收到LNK 4221警告(未定义新符号),这会导致LNK 2019(未解析的外部符号)。
这是引起问题的标题:
3d矢量
#ifndef VEC3_H
#define VEC3_H
// Standard library
#include <iostream>
#include <sstream>
// Internal
#include "SMath.h"
#include "Quaternion.h"
namespace Sapling {
template <typename T>
class Quaternion; ///< Forward
template <typename T> class Vec3 {
public:
// ...
void rotate(Vec3<T> axis, T radAngle) {
T sinHalfAngle = Math::sin(radAngle / 2);
T cosHalfAngle = Math::cos(radAngle / 2);
// Make a new quaternion [cos(w)|sin(w) vec]
Quaternion<T> rotation(axis.x * sinHalfAngle,
axis.y * sinHalfAngle,
axis.z * sinHalfAngle,
cosHalfAngle);
// Conjugate the rotation to eliminate the imaginary part
Quaternion<T> conjugate = rotation.getConjugate();
Quaternion<T> result = conjugate * (*this) * rotation; ///< frtl
x = result.x;
y = result.y;
z = result.z;
}
// ...
T x;
T y;
T z;
};
}
#endif
四元数
#ifndef QUATERNION_H
#define QUATERNION_H
// Standard library
#include <iostream>
#include <sstream>
// Internal
#include "Vec3.h"
namespace Sapling {
template <typename T>
class Vec3; ///< Forward
template <typename T> class Quaternion {
public:
// ...
Quaternion(Vec3<T> vec, T W) : x(vec.x), y(vec.y), z(vec.z), w(W) { }
// ...
// Relational vector operators
void operator*= (const Vec3<T>& v) {
x = -(x * v.x) - (y * v.y) - (z * v.z);
y = (w * v.x) + (y * v.z) - (z * v.y);
z = (w * v.y) + (z * v.x) - (x * v.z);
w = (w * v.z) + (x * v.y) - (y * v.x);
}
// ...
T x;
T y;
T z;
T w;
};
}
#endif ///< Include guard
我知道这两个类的数据都应该是私有的,但到目前为止我仍无法解决它。
那么,您能否向我解释为什么这仍然导致循环依赖?
感谢,并有一个愉快的一天 :)
最佳答案
作为一个简单的解决方案,我建议将Quaternion
分为两个类,QuaternionBase
不需要Vec3
,而Quaternion
本身是QuaternionBase
的子类,并从Vec3
引入构造函数:
// Vec3.h
...
#include <QuaternionBase.h>
...
template <typename T> class Vec3 {
public:
// ...
void rotate(Vec3<T> axis, T radAngle) {
...
QuaternionBase<T> rotation(axis.x * sinHalfAngle,
// QuaternionBase.h
template <typename T> class QuaternionBase {
public:
// all operations expect the constructor accepting Vec3
// Quaternion.h
#include <QuaternionBase.h>
#include <Vec3d.h>
template <typename T> class Quaternion : public QuaternionBase {
public:
// ...
Quaternion(Vec3<T> vec, T W) : QuaternionBase(vec.x, vec.y, vec.z, W) { }
另一种解决方案是为
Vec3d
创建基类,然后将访问操作(.x
等)移到那里。第三种解决方案是使
Quaternion(Vec3, T)
构造函数模板化,如下所示template<typename Vec>
Quaternion(Vec vec, T W) : x(vec.x), y(vec.y), z(vec.z), w(W) { }
希望这不会在代码的其他部分引入额外的歧义。