Function-Pointer , und Class Method



  • Ein Member-Funktionszeiger benötigt immer ein Objekt (Instanz) als zusätzliches Argument, für das es aufgerufen wird. Wenn du die Klassenfunktion statisch (static) machst, dann kannst du sie mit einem normalen Funktionszeiger aufrufen (&Foo::ProgressCallFunc), kannst jedoch innerhalb dieser Funktion nicht auf nicht-statische Member zugreifen.

    Wenn es eine reine C++-Lösung werden soll, dann nimm, wie erwähnt, std::function (s. Beispiel) oder eben als Template.

    Wenn es auch von C aus aufrufbar sein soll, dann übergebe als zusätzlichen Parameter void *, welches du dann innerhalb der Funktion wieder in einen Klassenzeiger zurück casten mußt.



  • @SoIntMan sagte in Function-Pointer , und Class Method:

    @Schlangenmensch ja sorry ich wollte auch die "ProgressCallFunc" Menber funktion zuweisen. und ich habe leider deinen Vorschlag nich verstanden😅

    Vielleicht hilft das weiter:
    https://stackoverflow.com/questions/6458612/c0x-proper-way-to-receive-a-lambda-as-parameter-by-reference

    Der Aufruf von dem Template könnte z.B. dann so aussehen (ungetestet):

    void DoFoo()
    {
       auto callBack = [this](int i)
          {
             ProgressCallFunc(i);
          };
       DoBar(callBack);
    }
    


  • Kleiner Hinweis noch, ich verwende (muss) VS 2008 C++ 🙂



  • @SoIntMan sagte in Function-Pointer , und Class Method:

    Kleiner Hinweis noch, ich verwende (muss) VS 2008 C++ 🙂

    Das ist ja erst 11 Jahre alt. Seitdem hat sich auch in der IT fast gar nichts verändert. Nur 3 neue C++-Standards. Sorry, aber wenn du nicht einmal C++11 nutzen kannst, dann ist irgendwas falsch.

    Ohne Lambdas? Dann mach dir ne eigene struct, speichere das this des Foo-Objektes darin und überlade operator(). Oder besser: beseitige den Grund, warum du noch VS 2008 nutzen musst.



  • @wob: so ist das nunmal , kann es nicht ändern.. 😞

    Naja ich bekomme das nicht hin , auch mit dem std::function und std:bind nich... ich denke ich lasse das einfach



  • @SoIntMan std::function ist auch erst ab C++11 verfügbar.

    Du kannst dir eine Hilfsklasse mit operator() erstellen:

    class Bar {
    public:
        template <typename Fn>
        static void DoBar(Fn f) {
            for (int i = 0; i < 100; ++i) {
                // Do hard work
                f(i);
            }
        }
    };
    
    class Foo {
    private:
        void ProgressCallFunc(int i);
    
    public:
        void DoFoo();
        friend class FooLambda;
    };
    
    class FooLambda {
        Foo *foo;
    
    public:
        explicit FooLambda(Foo *foo) : foo(foo) {}
        void operator()(int i) { foo->ProgressCallFunc(i); }
    };
    
    void Foo::ProgressCallFunc(int i) {
        //Get Progress state
    }
    
    void Foo::DoFoo() {
        // Call (in Thread)
        Bar::DoBar(FooLambda(this));
    }
    

    Das FooLambda könnte man durch ein Lambda ersetzen - seit 2011. Du musst eben irgendwie dafür sorgen, dass das ProgressCallFunc weiß, auf welches this es angewendet werden soll.



  • Hier noch ein kleines old-school Beispiel mit Pointer to Member Function:

    #include <iostream>
    
    class Foo;
    typedef void(Foo::*ProgressCallbackFunc)(int i);
    
    class Bar
    {
    public:
        static void DoBar(ProgressCallbackFunc funcptr, Foo& foo)
        {
            for (int i = 0; i <= 10; ++i)
            {
                (foo.*funcptr)(i*10);
            }
        }
    };
    
    class Foo
    {
    private:
        void ProgressCallFunc(int i)
        {
            std::cout << "Progress: " << i << "%\n";
        }
    
    public:
        void DoFoo()
        {
            Bar::DoBar(&Foo::ProgressCallFunc, *this);
        }
    };
    
    int main()
    {
        Foo foo;
        foo.DoFoo();
    }
    


  • Mahlzeit:

    @wob : Danke für dein Beispiel:) Aber für meinen Nutzen wird das zu Komplex😅

    @theta : Auch schönes Beispiel, aber ging das auch generisch?, so dass Foo irgend eine Klassen sein kann?



  • @SoIntMan sagte in Function-Pointer , und Class Method:

    aber ging das auch generisch?

    So?

    template  <typename MemFn, typename Instance>
    static void DoBar(MemFn funcptr, Instance& foo)
    


  • @SoIntMan, es gibt äquivalente Funktionalität in Boost (boost::function<..> und boost::bind(..)). Falls du das benutzen kannst, wäre das sicher ein Vorteil.


Anmelden zum Antworten