2017-04-17 12 views
0

ここでは、基本的に私は図形へのポインタを返す関数を書くように頼まれています。その点がどんな形でもないならば。この状況の良い代替手段はありますか?[ダウンキャスティング]

CFigure *ApplicationManager::GetFigure(int x, int y) const 
{ 
    //If a figure is found return a pointer to it. 
    //if this point (x,y) does not belong to any figure return NULL 
    int c = 0; 
    for (size_t i = 0; i < FigCount; i++) 
    { 
     if (dynamic_cast<CRectangle*> (FigList[i])) 
     { 
      CFigure* basepointer = FigList[i]; 
      Point A = static_cast<CRectangle*>(basepointer)->GetCorner1(); 
      Point B = static_cast<CRectangle*>(basepointer)->GetCorner2(); 

      if ((x>=A.x && x<=B.x) || (x<=A.x && x>=B.x)) 
      { 
       if ((y >= A.y && x <= B.y) || (y <= A.y && x >= B.y)) 
       { 
        c++; 
       } 
      } 
     } 
     else if (dynamic_cast<CCircle*> (FigList[i])) 
     { 
      CFigure* basepointer = FigList[i]; 
      Point A = static_cast<CCircle*>(basepointer)->getCntr(); 
      int B = static_cast<CCircle*>(basepointer)->GetRadius(); 

      double distance = sqrt(pow((x - A.x), 2) + pow((y - A.y), 2)); 
      if (distance<=(double)B) 
      { 
       c++; 
      } 
     } 
     else if (dynamic_cast<CLine*> (FigList[i])) 
     { 
      CFigure* basepointer = FigList[i]; 
      Point A = static_cast<CLine*>(basepointer)->getPoint1(); 
      Point B = static_cast<CLine*>(basepointer)->getpoint2(); 
      double distance1 = sqrt(pow((x - A.x), 2) + pow((y - A.y), 2)); //Distance from point to P1 
      double distance2 = sqrt(pow((x - B.x), 2) + pow((y - B.y), 2)); //Distance from Point to P2 
      double distance3 = sqrt(pow((B.x - A.x), 2) + pow((B.y - A.y), 2)); //Distance from P1 to P2 
      if (distance1+distance2==distance3) 
      { 
       c++; 
      } 
     } 
     else 
     { 
      CFigure* basepointer = FigList[i]; 
      Point p1 = static_cast<CTriangle*>(basepointer)->getp1(); 
      Point p2 = static_cast<CTriangle*>(basepointer)->getp2(); 
      Point p3 = static_cast<CTriangle*>(basepointer)->getp3(); 
      float alpha = (((float)p2.y - (float)p3.y)*((float)x - (float)p3.x) + ((float)p3.x - (float)p2.x)*((float)y - (float)p3.y))/
       (((float)p2.y - (float)p3.y)*((float)p1.x - (float)p3.x) + ((float)p3.x - (float)p2.x)*((float)p1.y - (float)p3.y)); 
      float beta = (((float)p3.y - (float)p1.y)*((float)x - (float)p3.x) + ((float)p1.x - (float)p3.x)*((float)y - (float)p3.y))/
       (((float)p2.y - (float)p3.y)*((float)p1.x - (float)p3.x) + ((float)p3.x - (float)p2.x)*((float)p1.y - (float)p3.y)); 
      float gamma = 1.0f - alpha - beta; 
      if (alpha>0 && beta>0 && gamma >0) 
      { 
       c++; 
      } 
     } 
    } 

    ///Add your code here to search for a figure given a point x,y 
    if (c==0) 
    { 
     return NULL; 
    } 

} 

ご覧のとおり、私はまだ何を返すべきかを決めていませんが、私の質問はここで最適なソリューションを動的にキャストしていますか?

-CLine、CTriangle、CRectangleとCCircleはすべてCFigure

+9

ヒット検出は、各クラスが実装する多態性メソッドを使用して実装する必要があります。 –

+0

@OliverCharlesworth申し訳ありませんが、ユーザーがクリックした場所を検出する機能が既にあります。 – AhmedKh

+0

@AhmedKh、Oliverが言っていることは、使用する正しいOOPテクニックではないということです。あなたは基本的には、図のタイプについて大きなswitch文を持っています。より良い方法は、ポイントが図の中にあるかどうかを示す 'bool'を返す' CFigure'クラス(抽象的な仮想メソッド)を 'contains'と呼んでいます。次に、フィギュアを通過し、キャスト不要の 'contains'を呼び出します。 – pcarter

答えて

1

virtual bool isclicked(int x, int y) = 0; 

これは純粋な仮想関数です。 CFigureのすべてのサブクラスで実装する必要があります。サブクラスの実装は、クリックがその境界内にあるかどうかをチェックし、それに応じてtrueまたはfalseを返します。

ザ・仮想関数や多型の魔法を通じて

CFigure *ApplicationManager::GetFigure(int x, int y) const 
{ 
    for (size_t i = 0; i < FigCount; i++) 
    { 
     if (FigList[i]->isclicked(x,y)) 
     { 
      return FigList[i]; 
     } 
    } 
    return nullptr; 
} 

のようなものにApplicationManager::GetFigure減少し、プログラムは、サブクラスのisclicked機能は、あなたの部分には何の更なる努力で呼び出される必要が把握されます。

+0

私は実際に感謝の多くを考えたことはありません! – AhmedKh

0

あなたがそれらを処理する方法を決定するための型をテストするのではなく、それぞれの派生型に処理を移動する仮想関数を使用することができますからクラスを派生しています。

代わりにこれを行うのVirtual Functions

を参照してください:

struct B {}; 
struct D1: B {}; 
struct D2: B {}; 

// ... 

void func(B* b) 
{ 
    int c = 0; 

    if(dynamic_cast<D1*>(b)) 
    { 
     // do D1 stuff 
     c = ... 
    } 
    else if(dynamic_cast<D2*>(b)) 
    { 
     // do D2 stuff 
     c = ... 
    } 
} 

あなたは、各サブタイプを持つように目指すべき自体を計算する方法を知っている:クラスCFigureアドオンで

struct B { virtual int calc() = 0; }; // virtual function calls derived type 
struct D1: B { int calc() override { int c = 0; /* D1 calculation */ return c; } }; 
struct D2: B { int calc() override { int c = 0; /* D2 calculation */ return c; } }; 

// ... 

void func(B* b) 
{ 
    int c = b->calc(); // virtual means the correct type's function is used 
} 
関連する問題