4

ElementクラスTriangleQuadrilateralが派生する抽象クラスがあるとします。

ただし、これらのクラスは、要素の形状に依存する補間メソッドと組み合わせて使用​​されると仮定します。InterpolationElementしたがって、基本的には、派生元の抽象クラスを作成しInterpolationTriangleますInterpolationQuadrilateral

次に、Triangleおよびクラスに補間機能を含めるために、タイプのQuadrilateralクラスにconst-referenceデータメンバーを追加します。つまり、次のようになります。ElementInterpolationElement

class Element
{
public:
    Element(const InterpolationElement& interp);

    const InterpolationElement& getInterpolation() const;

private:
    const InterpolationElement& interpolation;
};

InterpolationTriangle次に、クラスのローカル静的オブジェクトを次のようにインスタンス化するメソッド(Scott Meyers、Effective C ++で説明)を作成します。

const InterpolationTriangle& getInterpolationTriangle()
{
    static InterpolationTriangle interpolationTriangle;

    return interpolationTriangle;
}

そのため、クラスTriangleは次のように構成できます。

class Triangle : public Element
{
public:
    Triangle() : Element( getInterpolationTriangle() ) {}
};

これが私の質問です:私のクラスに補間メソッドを組み込むために、このアプローチは正しいElementですか?これはプロのシナリオで使用されますか?

(純粋な仮想として)クラスにすべての補間メソッドを直接実装Elementし、派生クラスTriangleとでそれらをオーバーライドすることができますQuadrilateral。ただし、新しい補間機能を改善または実装する必要があるたびに、これらのクラスでそれを実行する必要があるため、このアプローチは面倒に思えます。さらに、このアプローチを使用すると、クラスはどんどん大きくなります(多くのメソッド)。

ヒントやコメントをお聞かせください

前もって感謝します。


追加の詳細:

class InterpolationElement
{
public:
    InterpolationElement();

    virtual double interpolationMethod1(...) = 0;
                      :
    virtual double interpolationMethodN(...) = 0;
}

class InterpolationTriangle : public InterpolationElement
{
public:
    InterpolationTriangle () {}

    virtual double interpolationMethod1(...) { // interpolation for triangle }
                      :
    virtual double interpolationMethodN(...) { // interpolation for triangle }
}

class InterpolationQuadrilateral : public InterpolationElement
{
public:
    InterpolationTriangle () {}

    virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
                      :
    virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
4

5 に答える 5

1

提案には小さな問題が1つあります。基本クラスに補間関連のメソッドを追加し、コンストラクターを変更しました...

したがって、まず、この方法でそれを実行したい場合は、次のように実行する必要があります。

class Element
{
public:

private:
  // similar signature to a `clone` method
  virtual InterpolationElement* interpolation() const = 0;
};

class Triangle
{
public:

private:
  virtual InterpolationTriangle* interpolation() const
  {
    return new InterpolationTriangle();
  }
};

ここには2つの利点があります。

  • 各派生オブジェクトのコンストラクターを変更する必要がなくなりました
  • ストラテジーオブジェクトは、const補間されている現在のオブジェクトへの参照のように、計算中に状態を維持できるようになりました。

ただし、これでもElementクラスとその派生クラスを変更する必要があります。気になりませんか;)?

さて、デザインパターンを呼び出す時が来ました:Visitor

これは戦略の考え方とは少し異なり、適切に機能するためにダブルディスパッチに依存しています。Elementただし、(メソッドを使用して)1回の階層を微調整してから、必要なaccept数の操作を追加することができます。そしてそれは素晴らしいことです。

于 2010-08-13T06:51:42.323 に答える
1

クラスは、補間メソッドと組み合わせて使用​​されます。なぜこれらのメソッドはシングルトンオブジェクトにある必要があるのですか?ここのシングルトンは非常に問題があるように見えます。

class Element
{
public:
    virtual double interpolationMethod1(...) = 0;
                  :
    virtual double interpolationMethodN(...) = 0;

};

class Triangle : public Element
{
public:
    virtual double interpolationMethod1(...) { // interpolation for triangle }
                  :
    virtual double interpolationMethodN(...) { // interpolation for triangle }
}

また、SOへようこそ!

于 2010-08-12T21:14:14.100 に答える
1

これは私がここで答えた質問を彷彿とさせます。データコンテナの分離と戦略についての同じ考え。

于 2010-08-12T23:23:47.933 に答える
1

テンプレートはいつでも少し混乱させることができます。まず、トップクラスがあります。

class Element {
    public:
        virtual void calculate() const = 0;
};

...しかし、実際にはテンプレートであるクラスも階層の中央にあります。異なるパラメーターを持つテンプレートは異なるクラスであるため、テンプレートをトップレベルのクラスにすることはできません。アイデアは、要素に型パラメーターとして補間クラスを与えることです。

template <typename Interpolation>
class Element_Impl : public Element {
    protected:
        Interpolation m_interpolation;
};

そして補間クラス。兄弟ではないことに注意してください。兄弟である必要はないからです。

class InterpolationTriangle {
    public:
        double interpolate(double a, double b) const {
            std::cout << "interpolation triangle" << std::endl;
        }
};
class InterpolationQuadrilateral {
    public:
        double interpolate(double a, double b) const {
            std::cout << "interpolation quadrilateral" << std::endl;
        }
};

そして最後に、実際の要素と小さなメイン手順。

class Triangle : public Element_Impl<InterpolationTriangle> {
    public:
        void calculate() const {
            m_interpolation.interpolate(1.0, 2.0);
        }
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
    public:
        void calculate() const {
            m_interpolation.interpolate(2.0, 3.0);
        }
};
int main() {
    const Element &a = Triangle();
    const Element &b = Quadrilateral();
    a.calculate();
    b.calculate();
}

概要:

  • 必要に応じて、各要素の補間クラスを簡単に切り替えることができます。
  • Matthieuの例のように、二重のvtableアクセス(最初にElementのcalculate、次にInterpolationElementのintepolateメソッド)はありません。各要素は、コンパイル時に、使用している補間クラスを認識しています。
  • Element_Implは醜いビットですが、コピーパスタから私たちを救います。補間メソッドラッパーを実装することで、さらに拡張できます
  • http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

1つの方法は、静的メソッドを使用し、Element_Implでラッパーを定義することです-それでも1か所でのみです。

class Element {
    public:
        virtual void calculate() const = 0;
};

template <typename Interpolation>
class Element_Impl : public Element {
    protected:
        void interpolate(double, double) const {
            Interpolation::interpolate(1, 1);
        }
};

class InterpolationTriangle {
    public:
        static double interpolate(double a, double b) {
            std::cout << "interpolation triangle" << std::endl;
        }
};

class InterpolationQuadrilateral {
    public:
        static double interpolate(double a, double b) {
            std::cout << "interpolation quadrilateral" << std::endl;
        }
};

class Triangle : public Element_Impl<InterpolationTriangle> {
    public:
         void calculate() const {
            interpolate(1.0, 2.0);
        }
};

class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
    public:
        void calculate() const {
            interpolate(2.0, 3.0);
        }
};

int main() {
    const Element &a = Triangle();
    const Element &b = Quadrilateral();

    a.calculate();
    b.calculate();
}
于 2010-08-23T13:19:55.590 に答える
1

最初に頭に浮かぶのは、GoFデザインパターンビジターです。

私があなたの問題について理解していることから、このパターンはこの問題を正確に解決するために考えられています。

各Visitorオブジェクトは、オブジェクトに適用する補間手法またはアルゴリズムを定義します。

したがって、Elementクラスは、新しい機能ごとにまったく成長しません。配置されると、Visitorパターンにより、Baseクラスの定義に触れることなく機能を強化できます。

于 2010-08-23T14:03:40.757 に答える