0

this->メソッドの前に、またはDerived::タイプのオブジェクトのオブジェクトがない場合に、基本クラス メソッドが派生仮想メソッドを呼び出す理由を忘れていますDerived*。Arc::SetAngles(...) のコメント行を参照してください。

概要:

class Shape {
    public:
    //...
    protected:
    //...
    virtual void CalculateArea()=0;
    virtual void CalculateCenter()=0;
    private:
    //...
};

ベース:

void Arc::CalculateArea() {
    _area = 0.5 * _radius * _radius * _theta;
}

void Arc::CalculateCenter() {
    double e = GetEndAngle();
    double s = GetStartAngle();
    double d = e - s;

    double x = 0.0;
    double y = 0.0;
    double offset = 0.0;
    if(d < 0.0) {
        offset = a2de::A2DE_PI;
    }
    x = (GetPosition().GetX() + std::cos(((s + e) / 2.0) + offset) * _radius);
    y = (GetPosition().GetY() + -std::sin(((s + e) / 2.0) + offset) * _radius);
    _center = Vector2D(x, y);
    return;
}
void Arc::SetAngles(double startAngle, double endAngle) {
    if(startAngle < 0.0) {
        startAngle += A2DE_2PI;
    }
    if(endAngle < 0.0) {
        endAngle += A2DE_2PI;
    }
    _startAngle = std::fmod(startAngle, A2DE_2PI);
    _endAngle = std::fmod(endAngle, A2DE_2PI);

    //must call base version explicitly otherwise Sector:: versions are called when object is of type Sector* regardless if prefaced with this-> or nothing.

    Arc::CalculateCenter();
    Arc::CalculateLength();
    Arc::CalculateArea();
}

派生:

void Sector::CalculateArea() {
    _area = (_radius * _radius * _theta) / 2.0;
}

void Sector::CalculateCenter() {
    double x = (4 * _radius) / (3 * a2de::A2DE_PI);
    x += this->GetX();
    _center = Vector2D(x, GetY());
}
void Sector::SetAngles(double startAngle, double endAngle) {
    Arc::SetAngles(startAngle, endAngle);
    Sector::CalculateArea();
    Sector::CalculateCenter();
}
4

1 に答える 1

2

C++ は、次の選択肢を提供するように設計されています。

  1. 非仮想関数を使用 - 基本クラスの呼び出しは基本クラスのメソッドを使用します。
  2. 仮想関数を使用 - 基本クラスの呼び出しは派生クラス メソッドを使用します。

あなたの選択、あなたはどの行動をしたいですか?

そうは言っても、コードと継承階層には混乱があります。

セクター IS-A アークの場合、ほぼ間違いなく (ここでは幾何学的な議論であり、OO 設計の議論ではありません)、セクター面積とアーク面積の計算は同じである必要があります。そして、あなたのコードを見ると、それらは - Sector::CalculateArea(同じ数式の差分コード) を削除する可能性があります。

ただし、メソッドが 2 つの型で異なるという要件とCalculateCenter、基本クラス コードが派生クラスのオーバーライド (幾何学的引数と OO 引数) を利用できないという要件は、セクターがアークではないことを強く示唆しています。

コードは継承のために継承している可能性がありますが、この場合は不十分です。適切な継承が両方からのものであるかどうか自問してくださいShape

厳密に幾何学的な議論に戻ると、円弧は扇形ではありません: 円弧は円の周囲 (お好みであれば曲線) にあり、扇形は円の一部 (パイ型) です。これは、完全に異なる実装によってコードに表示されます。

于 2012-07-29T08:39:37.570 に答える