0

頂点とベクトルの 2 つのクラスがあります。演算子を使用して作業を簡素化しようとしています。以下に示すベクトルと頂点のクラスを調べると、頂点とベクトルの両方に演算子を実装しようとしています。

たとえば VertexA+VertexB = VectorC //あまり使われていない...

VertexA-VertexB = VectorC //非常に頻繁に使用できます

VertexA+VectorB = VertexC //非常に頻繁に使用できます

VertexA-VectorB = VertexC //非常に頻繁に使用できます

VectorA+VectorB = VectorC //使用

VectorA-VectorB = VectorC //使用

VectorA+VertexB = VertexC //使用

VectorA-VertexB = VertexC //使用

循環依存関係があることに気がつくでしょう。1 つのクラスの演算子が (参照やポインターではなく) 値によって返されるようにするため

回避策の 1 つを知っています。頂点をベクトルとして表現します。ただし、明確にするために2つの異なるクラスが好きなので、別の解決策があるかどうか疑問に思っていました。

#ifndef decimal
    #ifdef PRECISION
        #define decimal double
    #else
        #define decimal float
    #endif
#endif
class Vector;
class Vertex{
public:
    decimal x,y;
    const Vertex operator+(const Vector &other);
    const Vertex operator-(const Vector &other);
    const Vector operator+(const Vertex &other);
    const Vector operator-(const Vertex &other);
};

class Vector{
public:
    decimal x,y;
    const Vector operator+(const Vector &other) const {
        Vector result;
        result.x=this->x+other.x;
        result.y=this->y+other.y;
        return result;
    }
    const Vector operator-(const Vector &other) const {
        Vector result;
        result.x=this->x-other.x;
        result.y=this->y-other.y;
        return result;
    }
    const Vertex operator+(const Vertex &other) const {
        Vertex result;
        result.x=this->x+other.x;
        result.y=this->y+other.y;
        return result;
    }
    const Vertex operator-(const Vertex &other) const {
        Vertex result;
        result.x=this->x-other.x;
        result.y=this->y-other.y;
        return result;
    }
    decimal dot(const Vector &other) const{
        return this->x*other.x+this->y*other.y;
    }
    const decimal cross(const Vector &other) const{
        return this->x*other.y-this->y*other.x;
    }
};
4

2 に答える 2

0

このタイプのもの (算術データ型) のコードを簡単に記述できるようにするために、通常、Boost 演算子ヘッダーのような「演算子オーバーロード ヘルパー」と呼ばれる一連のテンプレートを使用します。私の実装をチェックアウトしてください。

このアプローチの利点は、演算子の実装が一貫していることです (operator+=実装は実装と一貫していoperator+ます)。

あなたの場合、Vertex& operator+=(const Vector& other)Vertex& operator-=(const Vector& other)Vector& operator+=(const Vector& other)、およびVector& operator-=(const Vector& other);のみを実装する場合。3 番目から 5 番目のケースをカバーします。どのように?

このコードを確認してください:

//Forward declaration needed:
class Vector;

struct Vertex : public dl32AdditionHelper<Vertex , Vector , true>,      //The last parameter is used to enable operator+ simmetry. That is, this covers cases 3 and 7.
                public dl32SubstractionHelper<Vertex , Vector , false>, //This covers case 4 (Simmetry si not enabled, see note bellow).
{
    float x , y;

    //For Vertex + Vector = Vertex
    Vertex& operator+=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }

    //For Vertex - Vector = Vertex
    Vertex& operator-=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }
};

struct Vector : public dl32AdditionHelper<Vector>,     //This covers case 5.
                public dl32SubstractionHelper<Vector>, //This covers case 6.
{
    float x , y;

    //For Vector + Vector = Vector
    Vector& operator+=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }

    //For Vector - Vector = Vector
    Vector& operator-=(const Vector& other)
    {
        x += other.x;
        y += other.y;

        return *this;
    }
};

それで全部です。

対称性に関する注意:対称性プロパティは、特定の演算子 # に対して、操作 a # b が b # a と等しいことを意味します。算術ヘルパーは、この機能を使用して対称演算子を提供します。たとえば、行列代数: m1 + m2 == m2 + m1 なので、 (A call to )operator+(const matrix_type_2& m1 , const matrix_type_1& m2)として実装されます。ご覧のとおり、対称性はケース 8 では機能しません。m2 + m1operator+(const matrix_type_1& m1 , const matrix_type_2& m2)

私のヘルパー実装は、最初のパラメーターの型を演算子の戻り値の型として使用します。これが、あなたの他のケースがカバーされない理由です。ただし、その場合は、ベクトルから頂点へ、またはその逆の変換を意味します。そのように実装を変更すると、すべてのケースをカバーできます。

于 2013-07-03T01:14:26.640 に答える