1

図形のライブラリを作成しようとしています。この宣言には、次のクラスShapeがあります。

#include "pos.h"
#ifndef SHAPE_H
#define SHAPE_H

class Shape{
protected:
    Pos pos;
public:
    Pos getPos();
    void setPos(Pos pos);
    virtual bool intersection(Shape&);

    Shape():pos((Pos){0,0}){}
    Shape(Pos pos):pos(pos){}
    Shape(int x, int y):pos((Pos){x,y}){}
};

#endif      /*  SHAPE_H */

ご覧のとおり、仮想関数メンバー(交差点)があります。この関数は、2つの形状が交差するかどうかを計算することを目的としています(円、長方形などの場合は問題ありません)。これらのクラス(CircleとRectangle)も宣言しました:

#include "pos.h"
#include "shape.h"

#ifndef RECTANGLE_H
class Rectangle;
#endif      /*  RECTANGLE_H */

#ifndef CIRCLE_H
#define CIRCLE_H

class Circle : public Shape{
private:
    int radius;
public:
    int getRadius(){return radius;}
    void setRadius(int radius){this->radius=radius;}

    bool containsPos(Pos p);
    bool intersection(Circle& c);
    bool intersection(Rectangle& r);

    Circle();
    Circle(Pos pos);
    Circle(int radius);
    Circle(Pos pos, int radius);
};

#endif      /*  CIRCLE_H    */

#include "pos.h"
#include "shape.h"

#ifndef CIRCLE_H
class Circle;
#endif      /*  CIRCLE_H */

#ifndef RECTANGLE_H
#define RECTANGLE_H

class Rectangle : public Shape{
private:
    int width;
    int height;
public:
    int getWidth(){return width;}
    int getHeight(){return height;}

    void setWidth(int width){this->width=width;}
    void setHeight(int height){this->height=height;}

    bool containsPos(Pos pos);
    bool intersection(Rectangle& r);
    bool intersection(Circle& c);

    Rectangle():Shape(),width(0),height(0){}
    Rectangle(int w, int h):Shape(),width(w),height(h){}
    Rectangle(Pos p, int w, int h):Shape(p), width(w),height(h){}
    Rectangle(int x, int y, int w, int h):Shape(x,y), width(w), height(h){}

};

#endif      /*  RECTANGLE_H */

ご覧のとおり、ShapeのサブクラスごとにShapeの各サブクラスにメンバー関数を作成しました。
良さそうですが問題があります。交差点を呼び出してShapeを指定すると(つまり、コンパイラはShapeを認識しません。たとえば、Shapesのベクトルから取得した場合)、パラメータとして機能しません(g ++:呼び出しに一致する関数がありません)。
パラメータが違う限り関数が違うので、Shapeの仮想関数を上書きしていないからだと思います(と思います)。
さて、この目標を達成するためのクールな方法があるのだろうか。

編集:現代のc ++デザインの第11章で、私の質問にもっと多くのものを見つけました。これは、マルチメソッド(実行時に型をチェックする必要がある引数を持つメソッド)に関するものです。この章のセクション9で、著者は、static_castを使用する場合、dynamic_castが適切なオプションであると述べています。これについてもっと見つけたら、もう一度編集します。
編集2:「最新のc ++デザイン」の第11章で、著者がゲーム内の異なる形状間の衝突検出がマルチメソッドの使用が必要になる典型的な問題であると述べていることをセクション2で見つけることができます。私は言いませんでしたが、この小さなライブラリはゲーム用であることが意図されていたので、まさに私が探していたものです。

4

2 に答える 2

2

デザインが間違っています。First ShapeにはBoundingRect、派生クラスが埋める領域のTop、Left、Bottom、Rightを返すという名前の仮想メソッドが必要です。次に、Shape.intersectionが最初に行うことは、境界の長方形が交差するかどうかを判断することです。ささいな運動。

今では難しくなっています。各形状は仮想名を提供する必要があります。これは、領域を正確Pathsに説明する線分のリスト/配列/ベジェ曲線を返します。次に、このメソッドは、いずれかの形状のパスが交差するかどうかを判別します。intersection

幸運を。

于 2013-01-27T03:46:27.320 に答える
1

実行時型情報を有効にし、実際にShapeクラスを受け取る交差メソッドを作成し、dynamic_castを使用して取得したオブジェクトを見つけてから、派生オブジェクトでオーバーロードされた交差呼び出しを呼び出します。

ただし、RTTIはコードの速度を大幅に低下させる可能性があり、形状のタイプごとに特別な関数を使用すると、コードの柔軟性と保守性が大幅に低下することに注意してください。リチャードが提案するような一般化されたソリューションは、長期的にはより有益である可能性があります。

于 2013-01-28T07:25:10.080 に答える