Außerhalb einer Klasse auf Events reagieren



  • Hallo zusammen,

    ich bin neu hier im Forum und habe eine Frage an euch.
    Aktuell nutze ich den Borland C++ Builder und würde gerne außerhalb einer selbst definierten Klasse auf ein Event der Klasse reagieren.

    Deklaration der Klasse:

    class Notify
    {
        private: int _changes;
    
        public: void changes(int value)
        {
            _changes = value;
        }
        public: int changes()
        {
            return _changes;
        }
    
        public: bool Change(int value)
        {
            try
            {
                if ((value < 0) || (value > 100))
                {
                    // Event aufrufen so dass auf dieses außerhalb der Klasse reagiert werden kann
                    return false;
                }
                else
                {
                    changes(value);
                    return true;
                }
            }
            catch (Exception &e)
            {
                return false;
            }
        }
    }
    

    Aufurf der Funktionen:

    #include <vcl.h>
    #include "Notify.cpp"
    
    TForm1 *Form1;
    Notify tmp;
    
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
    {
    }
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        tmp.Change(102);
    }
    
    // Ab hier soll auf das Event reagiert werden
    void __fastcall tmp::OnChanged(TObject *Sender)
    {
        // Mache irgendwas
    }
    

    Leider habe ich keine Idee, wie ich das auf eine einfache Art und Weise realisieren kann. In C# habe ich das wie folgt gelöst:

    ...
    
    public delegate void NotificationEvent(string name, object value);
    public event NotificationEvent OnNotification;
    
    ...
    
    OnNotification?.Invoke(Notifications[inti].sVarName, value);
    
    ...
    

    Das oben gezeigte Beispiel für C# ist natürlich unvollständig und dient nur zur Veranschaulichung.

    Ich würde mich freuen, wenn Ihr mir bei der Umsetzung in C++ behilflich sein könnt. Danke!

    Beste Grüße,
    Thar36



  • Hallo,

    auch der Borland C++ Builder unterstützt Events, z.B. TNotifyEvent, das Entscheidende daran ist das Schlüsselwort __closure.

    Als Beispiel:

    typedef void __fastcall (__closure *TMyEvent)(int x);
    
    // in der Klassendeklaration
    TMyEvent MyEvent;
    
    // Aufruf
    if (MyEvent != null)
      MyEvent(42);
    

    PS: Dein Beitrag sollte dann eher ins VCL-Forum.



  • Die nicht-standardkonforme und fehleranfällige Borland-eigene Version funktioniert mit dem borland-spezifischen Schlüsselwort __closure :

    class Notify
    {
       typedef void (__closure* HandlerFunc)( Notify& obj );
    
       unsigned int Value_;
       HandlerFunc  OnChange_;
    
    public:
       Notify() :
          Value( 0 )
       {
       }
    
       unsigned int value() const
       {
          return Value_;
       }
    
       void set_value( unsigned int Value )
       {
          if( Value != value() )
          {
             Value_ Value;
             if( OnChange_ )
             {
                OnChange_( *this );
             }
          }
       }
    
       void set_handler( HandlerFunc Handler )
       {
          OnChange_ = Handler;
       }
    };
    
    TForm1 *Form1;
    Notify tmp;
    
    __fastcall TForm1::TForm1( TComponent* Owner ) : 
       TForm( Owner )
    {
       tmp.set_handler( &OnChanged );
    }
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        tmp.set_value( 100 );
    }
    
    void TForm1::OnChanged( Notify& Value )
    {
        // Mache irgendwas
    }
    

    Die C++ konforme und etwas kompliziertere Version sieht dann so aus (setzt C++11 voraus):

    #include <functional>
    
    class Notify
    {
       using HandlerFunc = std::function<void (Notify&)>;
    
       unsigned int Value_;
       HandlerFunc OnChange_ ;
    
    public:
       Notify() :
          Value( 0 )
       {
       }
    
       unsigned int value() const
       {
          return Value_;
       }
    
       void set_value( unsigned int Value )
       {
          if( Value != value() )
          {
             Value_ Value;
             if( OnChange_ )
             {
                OnChange_( *this );
             }
          }
       }
    
       void set_handler( HandlerFunc Handler )
       {
          OnChange_ = Handler;
       }
    };
    
    TForm1 *Form1;
    Notify tmp;
    
    __fastcall TForm1::TForm1( TComponent* Owner ) : 
       TForm( Owner )
    {
       tmp.set_handler( std::bind( &TForm1::OnChanged, this, std::placeholders::_1 ) );
    }
    
    void __fastcall TForm1::Button1Click( TObject *Sender )
    {
        tmp.set_value( 100 );
    }
    
    void TForm1::OnChanged( Notify& Value )
    {
        // Mache irgendwas
    }
    

    Ungetestet runtergeschrieben.



  • @DocShoe: Hast du die Möglichkeit, deinen Code zu testen? Ich glaube da hat sich noch ein Fehler eingeschlichen bei der Zuweisung außerhalb der Klasse...

    Danke bis hier hin auf jeden Fall schon einmal für eure Antworten!





  • Danke euch für die Antworten.
    Ich habe das Problem mit eurer Unterstützung lösen können! 🙂


Log in to reply