Member functions pointer



  • hi,
    ich brauch euren rat, bin einfach zu blöd ein function einer klasse einer anderen klasse zu übergeben
    Also "void (CLASS::)()" zu "void()()"

    ich schreib einfach mal mein code rein.
    Wenn ich das versuche zu umschreiben, klappt das nicht so gut

    //Button.h 
    
    class Button 
    { 
    public: 
        Button (void); 
        ~Button (void); 
    
        void setFunc( void(*func)() ); 
        void Func(void) 
    
    private: 
        void (*m_Func)(); 
    };
    
    //Button.cpp
    
    void Button::Func(void)
    {
    	m_Func();
    }
    
    void Button::setFunc(void (*func)(void))
    {
    	m_Func = func;
    }
    
    //APP.cpp
    
    void APP::Play()
    {
        cout << "Play" << endl;
    } 
    
    int APP::Run(void)
    {
        Button btn;
        btn.setFunc(APP::Play);   <---------------------------------- Problem
    
    //main.cpp
    
    int main()
    {
        APP app;
        app.Run();
    }
    

    Ich hab es auch schon mit std::bind versucht, bekomm aber auch das nicht hin.
    Brauche bitte dringend eure hilfe.

    mfg



  • Du musst bei Memberfunktionen den Adressoperator verwenden...

    btn.setFunc(&APP::Play);
    


  • Achja und der Parameter von "setFunc" muss etwa so aussehen: (void (APP::*fp)())



  • ja, das schlagt mir mein vs2012 auch vor, geht aber auch nicht

    [EDIT]
    ja, das wäre ne möglichkeit, aber dann ist mir Button zu unflexibel



  • ja, das wäre ne möglichkeit, aber dann ist mir Button zu unflexibel

    Dein momentanes Design bietet sowieso keine Flexibilität. So müssen z.B alle Funktionen den Rückgabetyp void aufweisen und dürfen keine Parameter enthalten. Der Button hat keine Oberklasse (wtf?). Templates werden nicht verwendet und ohnehin: Eine Button-Klasse würde man ganz klar als Funktor implementieren.



  • ok,
    ich bin noch nicht so lange bei c++ und kenne mich daher noch nicht so gut aus.
    Bisher hat mein Butten.h immer ausgereicht.

    Von dem was du gerade sagst, versteh ich nicht wirklch was du mir sagen willst.
    Templates sagt mir was, aber was soll Oberklasse bedeuten und Funktor implementieren?

    Ich werde das jetzt, bzw morgen, mal nach googlen.
    aber vllt kannst du mir das in diesem zusammenhang besser erklären

    mfg


  • Mod

    Gestern in deinem anderen Thread, als du quasi die umgekehrte Frage gestellt hast, habe ich dir std::bind empfohlen. Nun muss die umgekehrte Empfehlung std::function sein. Alles was du hier und in dem anderen Thread mühsam versuchst, sind von den beiden längst viel besser gelöst worden:

    #include <functional>
    
    class Button
    {
      // Allgemeines Ding, das sich wie eine Funktion verhält, die void zurück gibt und keine Parameter hat:
      std::function<void()> f;
    
    public:
      // Akzeptiert alles, was sich irgendwie void()-artig aufrufen lässt:
      template <typename T> void set_function(T t) { f = t; }
    
      void invoke_function()
      {
        f();
      }
    };
    
    // von hier an dient alles nur der Demonstration:
    #include <iostream>
    using std::cout;
    
    void void_funktion_ohne_parameter() { cout << "void_funktion_ohne_parameter\n"; }
    
    void void_funktion_mit_parameter(int i) { cout << "void_funktion_mit_parameter: " << i << '\n'; }
    
    struct Foo 
    { 
      void nicht_statische_memberfunktion_ohne_parameter() { cout << "nicht_statische_memberfunktion_ohne_parameter\n"; }
      void nicht_statische_memberfunktion_mit_parameter(int i) { cout << "nicht_statische_memberfunktion_mit_parameter: " << i << '\n'; }
      static void statische_memberfunktion() { cout << "Langweilig!\n"; }
    };
    
    struct Functor
    {
      void operator()() { cout << "Functor\n"; }
    };
    
    int main()
    {
      using std::bind;
    
      Button button;
    
      button.set_function(void_funktion_ohne_parameter);  // Bei freien Funktionen kann man den Adressoperator auch weglassen
      button.invoke_function();
    
      button.set_function(bind(void_funktion_mit_parameter, 5));  // Schnürt die Funktion und den Parameter zusammen zu einer parameterlosen Funktion
      button.invoke_function();
    
      Foo foo;
    
      button.set_function(bind(&Foo::nicht_statische_memberfunktion_ohne_parameter, &foo));  // Bei Memberfunktionen ist der Adressoperator nötig
      button.invoke_function();
    
      button.set_function(bind(&Foo::nicht_statische_memberfunktion_mit_parameter, &foo, 5));  // Das Objekt auf dem eine Memberfunktion aufgerufen wird, ist quasi auch nur ein Paramter der Funktion und kann von bind zu einer parameterlosen Funktion zusammen geschnürt werden
      button.invoke_function();
    
      button.set_function(Foo::statische_memberfunktion);  // Statische Memberfunktionen sind auch nicht anders als freie Funktionen mit besonderem Namen.
      button.invoke_function();
    
      button.set_function(Functor());  // ALLES was irgendwie wie void() aufrufbar ist funktioniert
      button.invoke_function();
    
      button.set_function([](){cout<<"Lambda\n";});  // Das ist insbesondere praktisch für Lambdas
      button.invoke_function();
    }
    

    http://ideone.com/vAVaQT

    std::function und std::bind kochen natürlich auch nur mit Wasser. Aber bis du das selber mit diesem Komfort und Funktionsumfang nachprogrammiert hättest, würden ein paar Monate oder Jahre vergehen. Sei stattdessen froh, dass du dich nicht länger mit den Vorgängerversionen von bind und function herumschlagen musst! Die waren wirklich grausam 😮 . Wagemutige können hier unter "Deprecated in C++11" gucken:
    http://en.cppreference.com/w/cpp/utility/functional



  • danke,

    ihr habt mir sehr geholfen 🙂

    Eine frage hab ich aber noch
    Gibt es eine möglichkeit bind in der Button klasse zu benutzen?
    Also nicht

    button.set_function(bind(&Foo::nicht_statische_memberfunktion_ohne_parameter, &foo));
    

    sondern so das ich ganz normal "Foo::nicht_statische_memberfunktion_ohne_parameter" übergebe und dann mit bind arbeiten kann?

    mfg


  • Mod

    Für welches Objekt soll denn die nicht-statische Memberfunktion dann aufgerufen werden?



  • ja ok,

    ich weiss war ne blöde frage, aber hätte ja sein können das es da ne möglichkeit gibt.

    Dachte fragen kost nix 😃

    mfg


Log in to reply