2011-12-15 16 views
2

コンパイラは、2つの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-が私にエラーを与えます。誰かが私が間違っていることを教えてもらえますか?

+0

なぜ演算子はconstオブジェクトを返すのですか?削除してください。 – Dani

+0

エラーが発生した場所にコードを掲載できますか?また、正確に両方の演算子を定義する場所はどこですか? – Xeo

+0

@Xeoエラーが発生したコードを追加しました。私は上のバイナリ演算子の定義を持っています。右にスクロールしてすべてを見なければなりません。 – Xavier

答えて

4

クイックフィックスを行うには、を友人の代わりにVector3Dのフリー関数にします。友だちは、privateのメンバーにアクセスする場合にのみ必要です。Point3D(パブリックゲッターを使用しています)とVector3D(特に値からコンストラクターを使用して作成する)では実行できません。

operator+についても同様ですが、ここでは友情は必要ありません。あなたのコードが失敗した理由を今すぐに

friend宣言はクラス本体で見つかった最初あり、そしてそれはクラス宣言の後外側の名前空間で宣言されていない、その関数だけできれば引数に依存するルックアップによって見つけられます。つまり、引数のどれもがクラスのタイプのものでなければ、それは見つからないでしょう。あなたは、例えば、友情が必要とされていないときにそれらの自由機能することのいずれかによって、この問題を解決する、または明示的にヘッダに再び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); 

これらの言語の弁護士のためフリークアウトそこに、ここでは関係標準段落れる:関数の宣言のみがfriend宣言されると、私は信じている機能だけ

§7.3.1.2 [namespace.memdef] p3

[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]

3

発見されましたその引数の1つが宣言された型であるとき。 operator +はVector3Dを取りますので、コンパイラはVector3Dを探しています。演算子のみがPoint3Dを取るので、コンパイラはPoint3Dを参照しますがVector3Dは認識しないため、演算子は見つかりません。

Xeoが言ったように、関数宣言をクラスの外に移動すると、機能するはずです。

+1

あなたの最初の段落は正しいです、私は私の答えにもそれを加えたでしょう、私はちょうどオペレータが正確にそれらの演算子の定義が存在するかを確認するのを待っていた。 :) – Xeo

+0

そこに、私は行って、とにかくそれを追加しました。補償として私のupvoteを持っています。 ;) – Xeo

関連する問題