尝试减去两个Point3D对象时,编译器给我一个错误。我收到此错误:

Invalid operands to binary expression ('Point3D' and 'Point3D')

这是我在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;
};

Vector3D.cpp文件,它定义二进制运算符:
#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());}

这是我尝试从另一个减去Point3D的地方:
void AnimationService::handlePlayerMovement(double lastTime, double currentTime, Vector3D vector) {

    Point3D a;
    Point3D b;
    Vector3D result = a - b; // this is the problem line
}

奇怪的是二进制operator+确实可以工作,但是由于某种原因operator-给了我错误。谁能告诉我我在做什么错?

最佳答案

为了快速解决,请将operator-设为免费函数,而不是Vector3D的 friend 。仅当您要访问private成员时才需要友谊,而对于Point3D则不需要(使用公共(public)获取程序),而对于Vector3D则不需要(尤其是使用构造函数直接从值构造它)。
operator+也是如此,这里不需要友谊。

现在介绍为什么代码失败:

如果friend声明首先在类主体中找到,并且在类声明之后没有在封闭的命名空间中声明,则该函数只能通过依赖于参数的查找来找到,这意味着如果没有找到,则找不到该函数。参数是它的 friend 的类类型。您可以通过以下方式解决此问题:在不需要友谊时将其设置为自由函数,或者在 header 中再次在Vector3D类的主体之外明确声明它们,例如:

class Vector3D{
  friend const Point3D operator+(const Point3D& a, const Vector3D& b);
  friend const Vector3D operator-(const Point3D& a, const Point3D& b);
public:
  // bla bla, yadda yadda
};

// also *declare* them here
const Point3D operator+(const Point3D& a, const Vector3D& b);
const Vector3D operator+(const Point3D& a, const Point3D& b);

对于那些语言狂的人,这里是相关的标准段落:
§7.3.1.2 [namespace.memdef] p3

关于c++ - 我在运算符(operator)功能的运算符(operator)重载方面遇到麻烦,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8514686/

10-09 07:23
查看更多