Fibonacci OOP



  • Sehr schlechtes OOP Design.



  • was heißt hier schlechtes design, bei einem fibonacci-algo kannst du nunmal wenig OOPen, da ist es schon sinnlos, dass die funktion fib nicht statisch ist, schließlich hat die klasse keinerlei andere member...



  • #include <iostream>
    using namespace std;
    
    class Fibonacci
    {
    public:
       static int fib (int n)
        {
            if (n <= 1)
                return n;
            return fib (n-1) + fib (n-2);
        }
    };
    
    int main ()
    {
        cout << Fibonacci::fib (12);
    }
    


  • @SirLant:
    das macht den Code auch nicht wirklich besser



  • So geht OOP 💡

    #include <memory>
    #include <iostream>
    
    class Calculator {
      public:
        virtual int work() = 0;
        virtual ~Calculator() { }
    };
    
    class Calculator_factory {
      public:
        virtual Calculator* create_calculator(int n) = 0;
        virtual ~Calculator_factory_base() { }
    };
    
    class Fibonator : public Calculator {
      public:
        int work() { /* TODO: implement Fibonacci algorithm */ }
        Fibonator(int n): n(n) { }
      private:
        int n;
    };
    
    class Fibonator_factory : public Calculator_factory {
      public:
        Fibonator* create_calculator(int n);
    };
    
    Fibonator* Fibonator_factory::create_calculator(int n) {
      return new Fibonator(n);
    }
    
    int main() {
      Fibonator_factory fact;
      std::auto_ptr<Calculator> calc(fact.create_calculator(12));
      std::cout << calc->work() << std::endl;
    }
    


  • Shade Of Mine schrieb:

    @SirLant:
    das macht den Code auch nicht wirklich besser

    Also ich wüsste nicht wie man ne Funktion die _imho_ nicht in ne Klasse gehört,
    besser in ne Klasse packen kann.

    Ich persönlich würde es so machen (ungetestet):

    template < typename T >
    T fibonacci (const T & n)
    {
        if (n <= 1)
            return n;
        return fibonacci (n-1) + fibonacci (n-2);
    }
    

    Edit:
    Wenn ich mir Bashar's Code ansehe bevorzuge ich ne einfache Funktion in nem
    Namespace auf jeden Fall 🤡



  • SirLant schrieb:

    Also ich wüsste nicht wie man ne Funktion die _imho_ nicht in ne Klasse gehört,
    besser in ne Klasse packen kann.

    Und da haben wir die Lösung ja schon 🙂



  • Ich glaub ich hab nen Fehler in dem code gefunden:

    return new Fibonator(n);
    

    Wo ist das delete? 😕



  • Im Destruktor von std::auto_ptr. Aber danke fürs Anschauen, dachte schon die Mühe war ganz umsonst 😉



  • was macht denn auto_ptr?



  • auto_ptr ist ein sogenannter Smart-Pointer, der eine Besitzübertragungssemantik hat. Das heißt, er übernimmt die Verantwortung für ein Heap-Objekt und zerstört es, wenn er selbst zerstört wird. Wenn man einen auto_ptr kopiert oder zuweist, wird der Besitz und damit die Verantwortung weitergegeben -- es gibt jeweils nur einen auto_ptr, der auf ein bestimmtes Objekt zeigt (wenn man ihn nicht absichtlich falsch anwendet natürlich nur). Näheres erfährst du in jedem C++-Buch.



  • Wo wir gerade bei auto_ptr sind, was passiert bei Funktionsaufrufen mit dem
    Pointer als Argument, wird dann die Gültigkeit an nen auto_ptr übertragen welcher
    nach dem Aufruf nicht mehr lebt?

    Sowas meine ich:

    int main ()
    {
    auto_ptr<string> foo = new String ("bar");
    
    tolle_func (foo); // void toole_func (auto_ptr<string> foo);
    
    foo += "12"; 
    }
    


  • bashar, nur so als frage:

    class Calculator_factory { 
      public: 
        virtual Calculator* create_calculator(int n) = 0; 
        virtual ~Calculator_factory_base() { } 
    };
    

    gibts einen compiler, der die klasse mit dem dtor compiliert?



  • Nö, hab mich verschrieben.

    SirLant: Exakt.



  • @Sirlant: Du weißt aber schon, daß die Fibonacciszahlen exponentiell wachsen und die Anzahl der Funktionsaufrufe in Deiner Version proportional zur zu berechnenden Fibonacci-Zahl sind?



  • Das ist die richtige Lösung 😉

    #include <iostream> 
    using namespace std; 
    template<unsigned i> 
    struct fibonacci { 
      static const unsigned result = fibonacci<i-1>::result + fibonacci<i-2>::result; 
    }; 
    
    template<> 
    struct fibonacci<0> { 
      static const unsigned result = 1; 
    }; 
    
    template<> 
    struct fibonacci<1> { 
      static const unsigned result = 1; 
    };
    int main() { 
      cout << fibonacci<9>::result; 
    }
    

    Copyright von Rainer Baumann



  • Jester schrieb:

    @Sirlant: Du weißt aber schon, daß die Fibonacciszahlen exponentiell wachsen und die Anzahl der Funktionsaufrufe in Deiner Version proportional zur zu berechnenden Fibonacci-Zahl sind?

    Weiß ich, aber so ist es am kürzesten zu schreiben und sollte ja auch nur zeigen,
    wie ich so was schreiben würde.



  • SirLant schrieb:

    ... sollte ja auch nur zeigen,
    wie ich so was schreiben würde.

    Eben, und ich hoffe doch eigentlich, daß Du es iterativ schreiben würdest.



  • @pinguin: Hat aber im Prinzip wenig mit OOP zu tun? Viel eher mit Metaprogrammierung?! Nur weils hier doch um OOP ging 🙂

    MfG SideWinder



  • desert pinguin schrieb:

    Das ist die richtige Lösung 😉

    #include <iostream> 
    using namespace std; 
    template<unsigned i> 
    struct fibonacci { 
      static const unsigned result = fibonacci<i-1>::result + fibonacci<i-2>::result; 
    }; 
    
    template<> 
    struct fibonacci<0> { 
      static const unsigned result = 1; 
    }; 
    
    template<> 
    struct fibonacci<1> { 
      static const unsigned result = 1; 
    };
    int main() { 
      cout << fibonacci<9>::result; 
    }
    

    Copyright von Rainer Baumann

    2 fragen:
    1. wird das hier während des compilieren berechnet?
    2. ist das wirklich der richtige algorithmus? fiboacci war doch
    1,1,2,3,5,8,13...

    //edit aua... hab mich verguckt, die funktion berechnet die Zahl an der 9. stelle der liste oder?^^


Anmelden zum Antworten