The compiler gives me an error when trying to subtract two Point3D objects. I get this error:
Invalid operands to binary expression ('Point3D' and 'Point3D')
This is what I have in my Vector3D.h:
#include "Point3D.h"
using namespace std;
class Vector3D
{
friend const Point3D operator+(const Point3D& a, const Vector3D& b);
friend const Vector3D operator-(const Point3D& a, const Point3D& b);
public:
Vector3D() {}
Vector3D(float x, float y, float z);
Vector3D(Point3D const& originPoint, float theta, float distance);
float getX() const {return x;}
float getY() const {return y;}
float getZ() const {return z;}
static Vector3D minus(Point3D const& destination, Point3D const& origin);
Vector3D operator-(Vector3D const& other) const;
float dot(Vector3D const& other) const;
static float angleBetweenTwoVectorsZeroToPi(Vector3D const& a, Vector3D const& b);
static float angleBetweenTwoVectorsZeroToTwoPi(Vector3D const& a, Vector3D const& b);
Vector3D normalize() const;
float length() const;
//const float * const getArray() const {return &x;}
Vector3D multiply(float scalar) const;
bool operator==(Vector3D const& v) const;
float operator[] (int i) const;
private:
float x;
float y;
float z;
};
The Vector3D.cpp file which defines the binary operators:
#include "Vector3D.h"
#include "Math3D.h"
#include <math.h>
#include "MathConstants.h"
Vector3D::Vector3D(float x, float y, float z):
x(x), y(y), z(z)
{}
Vector3D::Vector3D(Point3D const& originPoint, float theta, float distance)
{
Point3D endPoint = Math3D::calcaultePoint3D(originPoint, theta, distance);
Vector3D result = minus(endPoint, originPoint);
this->x = result.x;
this->y = result.y;
this->z = result.z;
}
Vector3D Vector3D::minus(Point3D const& destination, Point3D const& origin)
{
return Vector3D(destination.getX() - origin.getX(),
destination.getY() - origin.getY(),
destination.getZ() - origin.getZ());
}
Vector3D Vector3D::operator-(Vector3D const& other) const {
return Vector3D(x-other.x, y-other.y, z-other.z);
}
float Vector3D::dot(const Vector3D &other) const
{
return x * other.x + y * other.y + z * other.z;
}
float Vector3D::length() const
{
return sqrtf(dot(*this));
}
Vector3D Vector3D::normalize() const
{
float len = length();
return Vector3D(getX()/len, getY()/len, getZ()/len);
}
Vector3D Vector3D::multiply(float scalar) const {
return Vector3D(x * scalar, y * scalar, z * scalar);
}
float Vector3D::angleBetweenTwoVectorsZeroToPi(const Vector3D &a, const Vector3D &b)
{
/*
* The result is between 0 and PI
*/
Vector3D unitA = a.normalize();
Vector3D unitB = b.normalize();
return acos(unitA.dot(unitB));
}
bool Vector3D::operator==(const Vector3D &v) const {
return (x == v.x) && (y == v.y) && (z == v.z);
}
float Vector3D::operator[](int i) const {
return (&x)[i];
}
float Vector3D::angleBetweenTwoVectorsZeroToTwoPi(const Vector3D &a, const Vector3D &b)
{
/*
* The result is between 0 and 2PI
*
* "Assuming a = [x1,y1] and b = [x2,y2] are two vectors with their bases at the
* origin, the non-negative angle between them measured counterclockwise
* from a to b is given by
*
* angle = mod(atan2(x1*y2-x2*y1,x1*x2+y1*y2),2*pi);
*
* As you can see, this bears a close relationship to the three-dimensional
* formula I wrote last July 10. The quantities, x1*y2-x2*y1 and x1*x2+y1*y2
* are, respectively, the sine and cosine of the counterclockwise angle from
* vector a to vector b, multiplied by the product of their norms - that is, their
* cross product and the dot product restricted to two dimensions. The 'atan2'
* function then gives the angle between them ranging from -pi to +pi, and the
* 'mod' operation changes this so as to range from 0 to 2*pi, as you requested."
*
* Roger Stafford
* http://www.mathworks.com/matlabcentral/newsreader/view_thread/151925
*/
float resultNegPiToPosPi = atan2f(a.x*b.y-b.x*a.y, a.x*b.x+a.y*b.y);
if (resultNegPiToPosPi < 0.0f)
{
resultNegPiToPosPi = resultNegPiToPosPi + 2*MathConstants::PI;
}
return resultNegPiToPosPi;
}
const Point3D operator+(const Point3D& a, const Vector3D& b) {return Point3D(a.getX()+b.getX(), a.getY()+b.getY(), a.getZ()+b.getZ());}
const Vector3D operator-(const Point3D& a, const Point3D& b) {return Vector3D(a.getX()-b.getX(), a.getY()-b.getY(), a.getZ()-b.getZ());}
This is where I try to subtract a Point3D from another:
void AnimationService::handlePlayerMovement(double lastTime, double currentTime, Vector3D vector) {
Point3D a;
Point3D b;
Vector3D result = a - b; // this is the problem line
}
The strange part is that the binary operator+ does work, but for some reason operator- gives me the error. Can anyone tell me what I’m doing wrong?
For a quick fix, make that
operator-a free function instead of a friend ofVector3D. Friendship is only needed when you want to accessprivatemembers, which you not do forPoint3D(you use the public getters), and which you especially not do for theVector3D(you use the constructor to directly construct it from the values).The same holds true for
operator+, no need for friendship here.Now on to why your code fails:
If a
frienddeclaration is first found in a class body, and it isn’t declared in the enclosing namespace after the class declaration, then the function can only be found by argument dependant lookup, meaning that it won’t be found if none of the arguments are of the class type it is a friend of. You can fix this by either making them free functions when the friendship isn’t needed, or by explicitly declaring them outside the body of theVector3Dclass again in the header, e.g.:For those language lawyer freaks out there, here is the relevant standard paragraph:
§7.3.1.2 [namespace.memdef] p3