Functorprobleme



  • Original erstellt von ChrisM:
    **Was macht man dann, wenn man nur eine ganz normale Funktion als Callback einsetzen will? Reicht es, wenn man dann für die Klasse 0 übergibt?
    **

    dann frag ich mich erstmal nach dem desingfehler.

    kannst zur nor noch ne notifier-klasse bauen, die globale funtionen isst.

    die clients sehen von den notifier-klassen ja eh nix, sondern rufen ja bei den wächtern methoden auf um sich zu registrieren.



  • kannst zur nor noch ne notifier-klasse bauen, die globale funtionen isst.

    Das verdoppelt nochmal die Anzahl der Notifierklassen. 😃

    die clients sehen von den notifier-klassen ja eh nix, sondern rufen ja bei den wächtern methoden auf um sich zu registrieren.

    Wie meinst du das? Ich denk, die Notifiertemplates werden direkt vom User instantiiert?

    ChrisM



  • Original erstellt von ChrisM:
    Wie meinst du das? Ich denk, die Notifiertemplates werden direkt vom User instantiiert?

    ich mein, daß die nur aufrufen blaevent.addWatcher(this,&Fasel::onMouse); und addWatcher ist ne template-methode, die schon alles richtug regeln wird.



  • Achso, du meinst, AddWatcher() wird dann für jeden Notifier einmal überladen, also z.B.

    template<class Klasse, class Return>
    AddWatcher(Klasse, (Return)*(void));
    
    template<class Klasse, class Return, class Param1, class Param2>
    AddWatcher(Klasse, (Return)*(Param1, Param));
    

    Seh ich das so richtig?

    ChrisM



  • Original erstellt von ChrisM:
    **template<class Klasse, class Return, class Param1, class Param2>
    AddWatcher(Klasse, (Return)*(Param1, Param));[/code]
    Seh ich das so richtig?
    **

    ja, aber eher noch

    template<class Klasse, class Return, class Param1, class Param2>
    AddWatcher(Klasse, (Return)*(Param1, Param),Param1,Param2);
    

    ob das das beste für dich ist, weiß ich nicht, aber ich hab sowas mal gemacht.
    und die 20 parameter kannste dir abscmingen. bau mal drei, und vermutlich reicht das. bau 4 erst, wenn du auch wirklich mal 4 parameter brauchst.



  • Danke erstmal, dass ihr überhaupt was postet 🙂

    Warum gibst du bei AddWatcher nochmal Werte für die Parameter an? Der Zeiger und this für Memberfunktionen müssten doch reichen, oder?

    Wenn mir dann noch jemand bei Frage 2 und 3 helfen könnte... 😃

    ChrisM



  • Original erstellt von ChrisM:
    Warum gibst du bei AddWatcher nochmal Werte für die Parameter an? Der Zeiger und this für Memberfunktionen müssten doch reichen, oder?
    ChrisM

    tja, ich dachte, du wolltest sagen können "wenn da ne mousemessage anliegt, dann ruf bitte "this->onMouse("imagemap1",23)" auf.



  • Nein, das ist ja meine Frage 3 😃

    Ich hab mir das so vorgestellt:
    Meine Mausklasse (um bei deinem Beispiel zu bleiben) hat ein Event als Member für das Klick-Ereignis. Nun speichert dieser Event normalerweise Funktionen mit 3 Ints (Koordinaten + Maustaste). Jetzt kommt aber ein Benutzer und initialisiert die Mausklasse 2 mal, er will aber nur eine Callbackfunktion benutzen. Also gibt er der Callbackfunktion als 4. Parameter noch einen int. Beim Erstellen der Notifiers wird dieser 4. Parameter vom Benutzer auf die ID der Maus festgelegt, also bei der einen Mausinstanz auf 1, bei der anderen auf 2. Trotzdem kann dieser Notifier im Event gespeichert werden, da er als Notifier mit 3 Parametern und nicht als einer mit 4 zählt!

    Geht das irgendwie? (in libsigc++ gehts wie gesagt mit sig::bind)

    ChrisM



  • *push*

    ChrisM



  • Bei solcher Callback-Problematik gibt meist eine Totschlag-Technik:
    Man definiere eine Klasse...
    1. Als Interface, d.h. Sie besitzt eine rein virtuelle Funktion z.B. "Execute()"

    2. Wird die Klasse als Klassen-Template angelegt, kann der Rückgabewert vom Typ <typename ...> sein

    3. Alle Parameter, die die Callback-Funktion ausführen soll, werden als Member gespeichert. Das erfordert allerdings entweder eine Ableitung, oder es wird eine Datenstruktur gespeichert (als void-Zeiger, oder durch Template-Technik während der Instantiierung).

    Wenn das Event aufgerufen wird, muß diesem nur ein Parameter "TCallBack* CallMe" übergeben werden, egal welche Ableitung davon nun *wirklich* übergeben wurde.

    class TCallback{
        void* Returned;
        void* Data;
        vitural void Execute(void)=0; // rein virtuell - das zwingt zum Überschreiben.
    };
    
    // Alternativ:
    
    template <typename D, typename R> class TCallBack{
        R* Returned;
        D* Data;
        virtual void Execute(void) =0;
    };
    
    // Implementierungs-Beispiel:
    
    class TMausCallBack : public TCallBack{
        // Der Konstruktor *kann* Parameter vorbelegen
        TMausCallBack(int& Param1, std:String& Param2, SomeClass* Param2){
            _param1=Param1;
            _param2=Param2;
            if(Param3)_param3=Param3; else _param3 = new SomeClass();  // Veranschalichte Plausibilitätsprüfung
        }
    
        virtual void Execute(){
            //Hier finden unglaublich komplexe Berechnungen statt ...
            Returning = 42;
        }
    
        int _param1;
    protected:
        std::String _param2;
        SomeClass* _param3;
    
             // Es muß nicht der gesamte Algorythmus in Execute liegen
             // Es kann eine Lambdafunktion oder statische Funktion sein...
        int Helfer(std::String& str);
    };
    
    //Anwendung:
    
    ...
    int THandler::DoHandle(int x, TCallBack* CallMe){
        if(CallMe){
            CallMe->Data+=x;     //Weise irgentwelche Parameter zu, erzeuge Daten...
            CallMe->Execute();
            return &((int*)CallMe->Returned);
        }
        return 0;     
    }
    

    Dieser Ansatz erfordert natürlich, daß im ausführenden Code eine bestimmte Ableitung erwartet wird ... ist also nicht wirklich generisch - sondern nur das, was man vor 20 Jahren darunter verstanden hätte. 😉
    Ich weiß, das ist eher eine Fleischhammer-Technik, aber Du willst es Dir ja auch nicht zu leicht machen!

    Außerdem könnte Dir da Boost vielleicht weiterhelfen:
    Schau' Dir doch mal Boost::function und Boost::Signals an, vielleicht könntest Du daraus ja etwas machen...
    http://www.highscore.de/cpp/boost/ereignisbehandlung.html



  • Gleich im Voraus: BinärWichtel ist ein Semi-Troll, dieser Thread ist von 2003. Wird (wahrscheinlich) gleich gesperrt.


Anmelden zum Antworten