Probleme mit Aufgabe zum Decorator Entwurfsmuster



  • Hallo Leute ich habe da ein kleines Problem...

    Ich habe anhand einer Aufgabenstellung dieses Programm geschrieben:
    Aufgabenstellung:

    - dynamisch zur Laufzeit Funktionen der Gestalt f(x) = sin(cos(cos(x))), also beliebige
    Kombinationen aus sin und cos, erstellen und hierzu das Decorator-Entwurfsmuster verwenden
    - als ConcreteComponent wird die Funktion f(x) = x verwendet.

    #include <iostream>
    #include <math.h>
    #include <exception>
    using namespace std;
    
    class Component
    {
          public:
                 virtual float execute(float x) const =0;
                 virtual ~Component() {}
    };
    class Identity : public Component
    {
          public:
                 virtual float execute(float x) const { return x;}
                 virtual ~Identity() {}
    };
    // Exception-Klasse, falls keine innere Funktion vorliegt
    class NoInnerFunction {};
    
    //Anfang Ergänzungen
    
    //Zusätzliche Ergänzungen1 - Anfang
    class SuperSinCos : public Component
    {
          public:
                 virtual void setInnerFunction(Component&);
    };
    //Zusätzliche Ergänzungen1 - Ende
    
    class Cos : public SuperSinCos
    {
          public:
                 Component *innerFunction;
                 void setInnerFunction(Component&);
                 float execute(float) const;
    };
    
    void Cos::setInnerFunction(Component& comp)
    {
         innerFunction = &comp;
    }
    
    float Cos::execute(float x) const
    {
              float a,b;
              try{
              a = innerFunction->execute(x);
              }
              catch(exception *)
              {}                  
              b = cos(a);
              return b;    
    }             
    
    class Sin : public SuperSinCos
    {
          public:
                 Component *innerFunction;
                 void setInnerFunction(Component&);
                 float execute(float) const;
    };
    
    void Sin::setInnerFunction(Component& comp)
    {
         innerFunction = &comp;
    }
    
    float Sin::execute(float x) const
    {
          float a,b;
          a = innerFunction->execute(x);
          b = sin(a);
          return b;
    }
    
    /* 
    class SinCos : public SuperSinCos, public Component
    {
          public:
                 Component *innerFunctionSin;
                 Component *innerFunctionCos;
                 void setInnerFunctionSin(Component&);
                 void setInnerFunctionCos(Component&);
                 float execute(float, float) const;
    };
    void SinCos::setInnerFunctionSin(Component& comp)
    {
         innerFunctionSin = &comp;
    }
    
    void SinCos::setInnerFunctionCos(Component& comp)
    {
         innerFunctionCos = &comp;
    }
    
    float SinCos::execute(float x, float y) const
    {
          float a,b,c;
          a = innerFunctionSin->execute(x);
          b = innerFunctionCos->execute(y);
          c = sin(a)+cos(b);
          return c;
    }
    */
    
    //Ende Ergänzungen
    
    int main()
    {
        Identity i;
        Cos c1;
        c1.setInnerFunction(i);
        Cos c2;
        c2.setInnerFunction(c1);
        Sin s;
        s.setInnerFunction(c2);
        cout << s.execute(0.0) << endl;
        system("Pause"); //Zusatz
        return 0;
    }
    

    Folgende Fehler muss ich aber noch korrigieren:

    - SuperSinCos muss setInnerfunction implementieren
    - SuperSinCos muss von Component abgeleitet sein, Sin und Cos dann von SuoperSinCos aber nicht auch noch von Component
    - innerFunction->execute(x) knallt wenn innerFunction keinen gültigen Zeiger enthält. => Exception entwerfen!

    Da ich aber schon mit dem bisherigen Programmieren größte Schwierigkeiten hatte, weiss ich momentan echt nicht, wie ich den Code noch umbauen muss. Vielleicht hat der ein oder ander ein paar Tipps für mich.
    1000 Dank schonmal.

    Grüße



  • Wozu benötigst Du SinCos?
    Das erledigt doch gerade das Pattern, oder?
    Also SinCos =

    Identity i;
        Cos c1;
        c1.setInnerFunction(i);  // cos(x)
        Sin sinCos;
        sinCos.setInnerFunction(c1); // sin(cos(x))
    

    Die Implementation von setInnerFunction benötigst Du nur einmal in SuperSinCos (irgendwie kein so guter Name). Diese sieht genauso so aus, wie Du sie jetzt bei den abgeleiteten Klassen hast. (Mal abgesehen davon, dass die Signatur irreführend ist: Du erwartest eine Referenz und merkst Dir einen Zeiger darauf. Der Aufrufer kann das nicht wissen, übergibt Dir ggf. eine lokale Variable. Damit wird der Zeiger auf die innerFunction dann völlig unbemerkt ungültig)

    Wenn Du keine gültige Funktion nach innerFunction steckst, dann knallt es immer, d.h. Du kannst es nicht über eine Exception abfangen. Du solltest aber im Konstrukor innerFunction auf NULL initialisieren und das in execute abprüfen.



  • Danke erstmal ... hab inzwischen denk ich das meiste hinbekommen, und könnte mir in den hintern beissen das ich nich selber drauf gekommen bin, war ja eigentlich nich schwer 😉

    Hier der aktuelle Code:

    #include <iostream>
    #include <math.h>
    using namespace std;
    
    class Component
    {
          public:
                 virtual float execute(float x) const =0;
                 virtual ~Component() {}
    };
    class Identity : public Component
    {
          public:
                 virtual float execute(float x) const {return x;}
                 virtual ~Identity() {}
    };
    // Exception-Klasse, falls keine innere Funktion vorliegt
    class NoInnerFunction {};
    
    //Anfang Ergänzungen
    
    //Zusätzliche Ergänzungen - Anfang
    
    class SuperSinCos : public Component
    {
          public:
                 Component *innerFunction;
                 void setInnerFunction(Component&);
    };
    
    void SuperSinCos::setInnerFunction(Component& comp)
    {    
         innerFunction = &comp;
    }
    
    //Zusätzliche Ergänzungen - Ende
    
    class Cos : public SuperSinCos
    {
          public:
                 Cos();
                 Component *innerFunction;
                 float execute(float) const;
    };
    
    Cos::Cos() 
    {
     innerFunction = NULL;
    }
    
    float Cos::execute(float x) const
    {
              float a,b;
              if(innerFunction != NULL)
                 a = innerFunction->execute(x);
              else 
                  {cout << "Zeiger1" << endl;}
              b = cos(a);
              return b;    
    }             
    
    class Sin : public SuperSinCos
    {
          public:
                 Sin();
                 Component *innerFunction;
                 float execute(float) const;
    };
    
    Sin::Sin() 
    {
     innerFunction = NULL;
    }
    
    float Sin::execute(float x) const
    {
          float a,b;
          if(innerFunction != NULL)
             a = innerFunction->execute(x);
          else 
               {cout << "Zeiger2" << endl;}
          b = sin(a);
          return b;
    }
    
    //Ende Ergänzungen
    
    int main()
    {
        Identity i;
        Cos c1;
        c1.setInnerFunction(i);
        Cos c2;
        c2.setInnerFunction(c1);
        Sin s;
        s.setInnerFunction(c2);
        cout << s.execute(0.0) << endl;
        system("Pause"); //Zusatz
        return 0;
    }
    

    Fehlt eigentlich nur noch das werfen der Exception, nur scheint es da wohl nen trick bei zu geben weil das nicht klappen will ...


Anmelden zum Antworten