Methodenzeiger als Member für CallBack



  • Hallo mal wieder,

    ich versuche einfach gesagt die Events (TNotifyEvent) von Delphi in C++, resp. G++ nachzubilden.
    Es scheint dallerdings in C++ nicht so einfach zu sein.

    Ein einfaches Beispiel wie ich mir das vorstellen würde:

    class a {
    public
    void(*CallBack) ();
    void Call() {
    Callback(); // hier sollte jetzt die Prozedur b->Test() aufgerufen werden.
    }

    class b {
    private
    void test();
    public:
    b(){
    m_a = new a();
    // hier wird es wild
    m_a->Callback = &test;
    }

    wie ich feststellen muss, geht das so nicht. Aus den Beschreibungen die im Inet
    bezülich Pointer auf Memberfunktionen kursieren, werde ich nicht ganz schlau.
    Gibt es überhaupt eine Möglichkeit für ein Konstrukt dieser Art unter C++?

    Gruß



  • Nein; es gibt nur mehr oder weniger häßliche Workarounds dafür, z.B. Fast Delegates oder Boost.Function.



  • Jop, das geht ganz gut.

    typedef void (b::*callback)();
    class a
    {
      b* obj_;
      callback cb_;
    
      public:
       a ( b* obj, callback cb )
       : obj_ ( obj ),
       cb_ ( cb )
       {}
    
      void call ()
      {
        (obj->*cb)();
      }
    };
    
    class b
    {
      public:
       void foo ()
       { std::cout << "hallo"; }
    }
    
    int main ()
    {
     b bar;
     a ( &bar, &b::foo );
    
     a->call();
    }
    

    Das einzige, was du da noch tun musst, ist das Objekt mitzugeben, da das auch benötigt wird.

    Ansonsten musst du da halt noch was rund herum basteln.



  • Allerdings muss a hier alle Klassen kennen, die a benutzten wollen 😕
    und ich müsste eine eigene CallBack für jeder dieser Klassen machen, oder?



  • Newbee2 schrieb:

    class a {
    public 
      void(*CallBack) ();
      void Call() {
        Callback(); // hier sollte jetzt die Prozedur b->Test() aufgerufen werden.
      }
    };
    

    CallBack ist ein Zeiger auf eine freie Funktion. Soweit ich weiß gibt es in Delphi eine besodere Sorte Funktionszeiger, die nicht nur die Adresse der Funktion sondern auch die Adresse des Objektes speichert.

    In C++ gibt es einen solchen "Doppel-Zeiger" nicht. Es gibt Zeiger auf Elementfunktionen. Diese binden aber nicht das Objekt:

    a dings;
    void (&a::*pmf)() = &a::Call; // pmf zeigt auf a::Call
    (dings.*pmf)();               // Element-Funktion für Objekt dings aufrufen
    

    C++ bietet einem aber die Möglichkeit, einen solchen generalisierten Funktionszeiger selbst zu bauen. Das wurde auch schon mehrfach gemacht. Such mal nach "Boost.Function" oder nach diversen "signal/slots"-Bibliotheken.

    Gruß,
    SP



  • Sebastian Pizer schrieb:

    void (&a::*pmf)() = &a::Call; // pmf zeigt auf a::Call
    

    Sorry, das & in &a::*pmf hat da nichts zu suchen und muss weg.



  • Sebastian Pizer schrieb:

    Sebastian Pizer schrieb:

    void (&a::*pmf)() = &a::Call; // pmf zeigt auf a::Call
    

    Sorry, das & in &a::*pmf hat da nichts zu suchen und muss weg.

    Ich kenne da eine Möglichkeit, dass du so Sachen anderst beheben kannst.. 😉

    Tritt auf die dunkle Seite bei und unterstütze unsere Gemeinschaft mit dem Symbolischen Anmelden. :p


Anmelden zum Antworten