Fibonacci OOP



  • Hi leute, ich habe mal versucht fibonacci OOP zu impelementieren, nur leider gibt er mir nur den eingegebenen wert zurück er rechnet auch was, merkt man an der Ausgabezeit 😃

    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    
    class Rekursiv
    
    {
    public:
    
    	int fib(int n);
    };
    
    int Rekursiv::fib (int n)
    {
    
    	if( n <= 2)	
    	{return 1;}
    	else 
    	{return (fib (n - 1) + fib (n - 2));}
    }
    
    int main()
    {
    Rekursiv nacci;
    
    int eing;	
    
    cout	<< "Geben sie die FibonacciStelle ein"<<endl;
    cin		>> eing;
    
    nacci.fib(eing);
    cout <<eing<<endl;
    
    return 0;
    }
    


  • Was hat das mit OOP zu tun?

    btw: dein Fehler ist, dass du die eingegebene Zahl ausgibst, und nicht das Ergebnis der Berechnung



  • 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


Anmelden zum Antworten