Frage

Angenommen, wir haben eine abstrakte Klasse Element aus denen Klassen Triangle und Quadrilateral stammen aus.

Nehmen wir doch, dass diese Klassen in Verbindung mit Interpolation verwendet werden, Methoden, die von der Form des Elements ab. Also, im Grunde schaffen wir eine abstrakte Klasse InterpolationElement, aus denen wir InterpolationTriangle und InterpolationQuadrilateral ableiten.

Dann enthalten die Interpolation Funktionalität in den Triangle und Quadrilateral Klassen, fügen wir ein const-Referenzdatenelement in der Klasse Element vom Typ InterpolationElement, das heißt:

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

    const InterpolationElement& getInterpolation() const;

private:
    const InterpolationElement& interpolation;
};

Wir erstellen dann eine Methode (wie von Scott Meyers, Effective C ++), die einem lokalen statischen Objekt der Klasse InterpolationTriangle instanziiert als

const InterpolationTriangle& getInterpolationTriangle()
{
    static InterpolationTriangle interpolationTriangle;

    return interpolationTriangle;
}

Damit Klasse Triangle kann wie konstruiert werden:

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

Hier ist meine Frage: ist dieser Ansatz richtig, um Interpolationsverfahren auf meiner Klasse Element zu integrieren? Ist das in der professionellen Szenarien?

konnte es umsetzen direkt alle Interpolationsverfahren auf Klasse Element (als rein virtuellen) und die Überschreibung sie in der abgeleiteten Klassen Triangle und Quadrilateral. Allerdings scheint dieser Ansatz mir umständlich zu sein, da ich jedes Mal verbessern müssen oder neue Interpolation Funktionalitäten zu implementieren ich würde, dass auf diesen Klassen zu tun. Darüber hinaus erhalten die Klassen größer und größer (viele Methoden) mit diesem Ansatz.

Ich möchte von Ihnen einige Tipps und Kommentare hören

Vielen Dank im Voraus.


Weitere Informationen:

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}
}
War es hilfreich?

Lösung

Die Klassen werden in Verbindung mit Interpolation Methoden . Warum brauchen diese Methoden in einem Singleton-Objekt sein? Die Singleton hier sieht sehr problematisch.

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 }
}

Auch Willkommen zu SO!

Andere Tipps

Das erinnert an eine Frage, die ich hier . Die gleiche Idee über die Trennung von Datencontainer und die Strategien.

Es gibt ein kleines Problem mit dem Vorschlag: Sie haben eine Interpolation verwandtes Verfahren zu Ihrer Basisklasse hinzugefügt, und Sie haben den Konstruktor ...

geändert

Also zunächst einmal, wenn Sie es wünschen es auf diese Art und Weise zu tun, hier ist, wie Sie es tun sollten:

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();
  }
};

Es gibt zwei Vorteile hier:

  • Es ist nicht mehr notwendig, den Konstruktor jedes der abgeleiteten Objekte zu ändern
  • Die Strategie Objekt ist nicht mehr const, die es Zustand während der Berechnung ... wie ein Verweis auf das aktuelle Objekt wird interpoliert pflegen können.

Dies erfordert jedoch noch die Element Klasse zu ändern, und jeder seiner abgeleiteten Klassen. Ist es nicht stören;)

Nun, es ist an der Zeit (einmal) auf ein Design-Muster zu nennen:. Visitor

Es ist ein wenig anders als die Strategie Idee, richtig auf Doppel-Ausgabe an der Arbeit zu verlassen. Allerdings ermöglicht es Ihnen, die Hierarchie der Elements zwicken ONCE (mit einer accept-Methode) und dann so viele Operationen hinzufügen, wie Sie es wünschen. Und das ist groß.

Sie können immer Chaos ein wenig mit Vorlagen. Zuerst haben wir eine Top-Klasse.

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

... aber dann haben wir auch eine Klasse in der Mitte der Hierarchie, die eigentlich eine Vorlage. Vorlage kann nicht die Top-Level-Klasse sein, als Vorlagen mit unterschiedlichen Parametern verschiedene Klassen sind. Die Idee ist, dass wir eine Interpolation Klasse als Typ-Parameter auf das Element geben.

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

Und Interpolation Klassen. Beachten Sie, sind sie Geschwister nicht, weil sie nicht brauchen.

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;
        }
};

Und schließlich die realen Elemente und die kleinen Hauptverfahren.

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();
}

Zusammenfassung:

  • Sie können leicht Interpolation Klasse wechseln für jedes Element, wenn nötig.
  • gibt es keine doppelten VTable-Zugang (zuerst berechnet Elemente der und dann für InterpolationElement der intepolate Methoden), wie in dem Beispiel des Matthieu. Jedes Element kennt bei der Kompilierung der Interpolation Klasse es verwendet.
  • Element_Impl ist eine hässliche wenig, aber es rettet uns von copypasta. Sie können es noch weiter ausbauen durch Interpolationsverfahren Wrapper Umsetzung
  • http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

Eine Möglichkeit ist, statische Methoden zu verwenden, und den einen Wrapper in Element_Impl -. Nur noch an einem Ort

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();
}

Was zuerst mir in den Sinn kommt, ist die GoF Design Muster Besucher

Von dem, was ich von Ihrem Problem zu verstehen, dieses Muster zu genau konzipiert ist dieses Problem zu lösen.

Jeder Besucher Objekt definiert eine Interpolationstechnik oder einen Algorithmus zu Ihrem Objekt anzuwenden.

So ist die Element-Klasse wächst nicht überhaupt mit jedem neuen functionnality. Einmal installiert, ermöglicht das Besuchermuster anzureichern functionnality, ohne auf die Basisklassendefinition zu berühren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top