[gelöst] function pointer von vererbten Klassen in Basis-Klasse speichern



  • Moin Moin,

    ich arbeite mich gerade in das Thema function pointer ein.

    Ich habe einen Wrapper mit einer privaten Klasse Base. Von Base sollen mehrere Klassen erben, die alle einige Klassenspezifische Funktionen mit der gleichen Signatur (void func()) haben.
    Ich möchte, dass eine geerbte Klasse alle eigenen Funktionen als Function Pointer in einem Container speichert, der in der Base-Klasse definiert ist. Die Function Pointer sollen dann einfach von der Wrapper-Klasse aus aufgerufen werden.

    Optimal wäre es, wenn ich in der geerbten Klasse nur eine virtuelle Funktion "registerFunctions()" implementieren muss, in der auf möglichst einfache Weise die function Pointer erstellt und gespeichert werden.

    Blöde Frage, aber trotzdem:
    Wie mache ich das und ist das so überhaupt möglich?

    Ich habe es schon mit den eigentlichen function pointern void(*func)()und mit std::function versucht und bin immer daran gescheitert, dass ich einen vererbten Klassentyp als Basis-Klassentyp speichern muss.
    Und auf ein switch-case in der vererbten Klasse möchte ich eigentlich verzichten...

    Viele Grüße
    Cherup



  • Cherup schrieb:

    ...
    std::function versucht und bin immer daran gescheitert, dass ich einen vererbten Klassentyp als Basis-Klassentyp speichern muss.

    Erklär mal



  • Ich definiere den vector mit den Funktionspointern ja in der Base-Klasse, daher muss er ja in etwa wie "vector<std::function<void(Base*)>>" aussehen. Ich kenne den Klassentyp der vererbten Klasse ja nicht.
    Die Funktionen, die ich dem vector zuweisen möchte haben aber den Typ std::function<void(Derived*)>.

    //vector in Base:
    std::vector<std::function<void(Base*)>> vec;
    
    //Pointer in der Derived erstellen:
    std::function<void(Derived*)> test = &Derived::func(); 
    //funktioniert, kann aber dem vector nicht zugewiesen werden.
    std::function<void(Base*)> test = &Derived::func(); 
    //funktioniert nicht, gibt mir folgenden Fehler in functional zurück:
    //functional:558: error: pointer to member type 'void (Derived::)()' incompatible with object type 'Wrapper::Base'
    

    Da liegt das eigentliche Problem. Obwohl Derived ja eigentlich auch Base ist...

    Vielleicht mache ich auch einfach nur einen Denkfehler...



  • //vector in Base:
    std::vector<std::function<void()>> vec;
    
    //Pointer in der Derived erstellen:
    std::function<void()> test = [=]()mutable{ func(); }; // mutable nur, wenn func nicht const
    
    vec.push_back(test);
    


  • Danke, das klappt, da wäre ich wohl nie drauf gekommen...
    Kannst du mir die Syntax genauer erklären? ich verstehe z.B. das [=] nicht.

    Andere Frage: wird damit die Funktion der Instanz der Klasse aufgerufen? Ich greife in den Funktionen auf member-Variablen zu...



  • Cherup schrieb:

    Kannst du mir die Syntax genauer erklären? ich verstehe z.B. das [=] nicht.

    Das macht den this Pointer zugreifbar. Stichwort lambda.

    Cherup schrieb:

    Andere Frage: wird damit die Funktion der Instanz der Klasse aufgerufen? Ich greife in den Funktionen auf member-Variablen zu...

    Ja



  • Danke 🙂

    Ich werd mich wohl auch mal mit Lambda-Ausdrücken beschäftigen müssen, hab ich noch nicht mit gearbeitet...





  • Danke, werds lesen 🙂

    Noch eine blöde Frage:
    Kann man den Ausdruck "[=]()mutable{ func(); }" irgendwie vereinfachen? Also das man das nicht bei jeder Funktion komplett schreiben muss, sondern ein einfacheres Alias hat?

    Mein Kopf ist grad etwas dicht...



  • Auf die Schnelle:

    #include <iostream>
    
    class foo
    {
    public:
      void a() {  std::cerr << 1 << "\n"; }
      void b() {  std::cerr << 2 << "\n"; }
      void fill()
      {
        auto mkf = [=](auto f)
        {
          return [=]() mutable { (this->*f)(); };
        };
    
        std::function<void()> x = mkf(&foo::a);
        x();
        std::function<void()> y = mkf(&foo::b);
        y();
      }
     };
    
    int main()
    {
      foo aFoo;
      aFoo.fill();
    }
    

    Ob das Ganze Sinn macht, bezweifle ich allerdings ...



  • Stimmt, das macht relativ wenig Sinn. Hatte gehofft, irgendwas in die Base-Klasse einbauen zu können, das die Funktionserstellung vereinfacht...
    Tja dann muss es halt so gehen 😉

    Danke für deine Hilfe 🙂


Log in to reply