我试图为游戏制作一个简单的2D坐标矢量类,但是当重写operator +时我遇到了问题。向量使用模板来设置其X和Y值的数据类型,因此所有函数(包括运算符重载)都必须使用模板。所有成员函数都可以正常工作,但非成员函数会给我一个错误。
这是错误:
In function `ZNK13AxisAlignedBB8maxPointEv':
undefined reference to `Vector<double> operator+<double>(Vector<double> const&, Vector<double> const&)'
以下是给我错误的代码:
Vector2d AxisAlignedBB::maxPoint() const {
return position + dimensions;
//position and dimensions are both type Vector<double>
}
这是函数的声明:
template <typename T> class Vector {
//class definition...
}
template<typename T>
Vector<T> operator+(const Vector<T>&, const Vector<T>&);
这是该功能的实现。据我所知,它应符合上述声明:
template<typename T> Vector<T> operator+(const Vector<T>& v1, const Vector<T>& v2){
return v1.add(v2); //returns Vector<T>(v1.x + v2.x, v1.y + v2.y)
}
我也在我的游戏中使用SFML作为图形,所以为了确保,我查看了SFML / System / Vector2.hpp,它与我的矢量基本上完成相同的工作。这里有相同函数的版本,除了参数名称外,它看起来与我的相同:
template <typename T>
Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right);
我无法访问SFML的功能实现,所以我无法检查以确保它是相同的。我之所以不使用SFML的载体,是因为它们不包含大小,交叉产品等功能。另外,我真的很懒惰而且不喜欢它们。我想把&#34; sf ::&#34;在一切之前。
编辑:Vector.h / .cpp
的全文Vector.h:
#ifndef VECTOR_H
#define VECTOR_H
#include <SFML/System/Vector2.hpp>
template <typename T> class Vector {
public:
T x;
T y;
Vector<T>() : x(0), y(0) {};
Vector<T>(T ax, T ay) : x(ax), y(ay) {};
///Conversion from SFML vector of same type
Vector<T>(const sf::Vector2<T>& v) : x(v.x), y(v.y) {};
/**
* Returns the magnitude of this Vector<T>.
*/
T mag() const;
/**
* Returns the square of the magnitude of this Vector<T>, cutting
* out an expensive sqrt() call.
*/
T magSquared() const;
/**
* Returns the dot product of this and the given Vector<T>.
*/
T dot(const Vector<T>&) const;
/**
* Returns the distance between this and the given Vector<T>.
*/
T distance(const Vector<T>&) const;
/**
* Returns the square of the distance between this and the given Vector<T>,
* cutting out an expensive sqrt() call.
*/
T distanceSquared(const Vector<T>&) const;
/**
* Returns a new Vector<T> with the same coordinates.
*/
Vector<T> clone() const;
/**
* Returns the resultant Vector<T> of adding the given Vector<T>.
*/
Vector<T> add(const Vector<T>&) const;
/**
* Returns the resulting Vector<T> of subtracting the given Vector<T>.
*/
Vector<T> sub(const Vector<T>&) const;
/**
* Returns the resulting Vector<T> of multiplying this Vector<T> by
* the given scalar value.
*/
Vector<T> mult(T) const;
/**
* Returns the projection of this Vector<T> onto the given axis.
* In this function, this Vector<T> is the point to be projected
* and the given Vector<T> is the axis.
*/
Vector<T> proj(const Vector<T>&) const;
/**
* Returns the projection of the given Vector<T> on to this axis.
* In this function, this Vector<T> acts as the axis and the given
* Vector<T> is the point to be projected.
*/
Vector<T> proj2(const Vector<T>&) const;
/**
* Revolves this Vector<T> about the origin by the given angle in radians.
*/
Vector<T> revolve(T) const;
/**
* Revolves this Vector<T> about the given Vector<T>
* by the given angle in radians.
*/
Vector<T> revolveAbout(T, const Vector<T>&) const;
/**
* Returns the normalized version of this Vector<T>.
*/
Vector<T> normalize() const;
/**
* Performs a 2D cross product with the given Vector<T>.
*/
T crossVector(const Vector<T>&) const;
/**
* Performs a 2D cross product with the given scalar value.
* This function performs the operation this X value.
*/
Vector<T> crossScalar(T) const;
/**
* Performs a 2D cross product with the given scalar value.
* This function performs the operation value X this.
*/
Vector<T> crossScalar2(T) const;
Vector<T>& operator+=(const Vector<T>& v){
x += v.x;
y += v.y;
return *this;
}
Vector<T>& operator-=(const Vector<T>& v){
x -= v.x;
y -= v.y;
return *this;
}
Vector<T>& operator*=(const T t){
x *= t;
y *= t;
return *this;
}
Vector<T>& operator/=(const T t){
x /= t;
y /= t;
return *this;
}
Vector<T> operator-(){
return Vector(-x, -y);
}
///Conversion from SFML vector of same type
Vector<T>& operator=(const sf::Vector2<T>&);
///Conversion to SFML vector of same type
operator sf::Vector2<T>();
protected:
private:
};
typedef Vector<double> Vector2d;
typedef Vector<float> Vector2f;
typedef Vector<int> Vector2i;
template<typename T> Vector<T> operator+(const Vector<T>& v1, const Vector<T>& v2){
return Vector<T>(v1.x + v2.x, v1.y + v2.y);
}
template<typename T> Vector<T> operator-(const Vector<T>& v1, const Vector<T>& v2){
return Vector<T>(v1.x - v2.x, v1.y - v2.y);
}
template<typename T> Vector<T> operator*(const Vector<T>& v, const T t){
return Vector<T>(v.x * t, v.y * t);
}
template<typename T> Vector<T> operator*(const T t, const Vector<T>& v){
return Vector<T>(v.x * t, v.y * t);
}
template<typename T> Vector<T> operator/(const Vector<T>& v, const T t){
return Vector<T>(v.x / t, v.y / t);
}
#endif // VECTOR_H
Vector.cpp:
#include "Vector.h"
#include <cmath>
template<typename T> T Vector<T>::mag() const {
return std::sqrt(magSquared());
}
template<typename T> T Vector<T>::magSquared() const {
return std::pow(x, 2) + std::pow(y, 2);
}
template<typename T> T Vector<T>::dot(const Vector<T>& v) const {
return (v.x * x) + (v.y * y);
}
template<typename T> T Vector<T>::distanceSquared(const Vector<T>& v) const {
return sub(v).magSquared();
}
template<typename T> T Vector<T>::distance(const Vector<T>& v) const {
return sub(v).mag();
}
template<typename T> Vector<T> Vector<T>::clone() const {
return Vector(x, y);
}
template<typename T> Vector<T> Vector<T>::add(const Vector<T>& v) const {
return Vector(x + v.x, y + v.y);
}
template<typename T> Vector<T> Vector<T>::sub(const Vector<T>& v) const {
return Vector(x - v.x, y - v.y);
}
template<typename T> Vector<T> Vector<T>::mult(T t) const {
return Vector(t * x, t * y);
}
template<typename T> Vector<T> Vector<T>::proj(const Vector<T>& axis) const {
return axis.proj2(*this);
}
template<typename T> Vector<T> Vector<T>::proj2(const Vector<T>& point) const {
T p = dot(point) / magSquared();
return mult(p);
}
template<typename T> Vector<T> Vector<T>::revolve(T a) const {
a += std::atan2(y, x);
return Vector(mag() * std::cos(a), mag() * std::sin(a));
}
template<typename T> Vector<T> Vector<T>::revolveAbout(T a, const Vector<T>& v) const {
return sub(v).revolve(a).add(v);
}
template<typename T> Vector<T> Vector<T>::normalize() const {
return Vector(x / mag(), y / mag());
}
template<typename T> T Vector<T>::crossVector(const Vector<T>& v) const{
return x * v.y - y * v.x;
}
template<typename T> Vector<T> Vector<T>::crossScalar(T t) const {
return Vector(t * y, -t * x);
}
template<typename T> Vector<T> Vector<T>::crossScalar2(T t) const {
return crossScalar(-t);
}
template<typename T> Vector<T>& Vector<T>::operator=(const sf::Vector2<T>& v){
x = v.x;
y = v.y;
return *this;
}
template<typename T> Vector<T>::operator sf::Vector2<T>(){
return sf::Vector2<T>(x, y);
}