Function-Pointer , und Class Method



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

    Ok dachte funktionptr und member -funktionptr machen keinen unterschied

    Naja, stell dir doch mal vor, dass du bei Memberfunktionen irgendwie noch übertragen musst, um welches konkrete Objekt deiner Klasse es sich handelt. In anderen Sprachen, wie z.B. Python, musst du bei Memberfunktionen self (entspricht this in C++) explizit als ersten Parameter angeben. In C++ passiert das implizit, ist aber im Prinzip der Grund, warum Funktion und Member-Funktion unterschiedlich sind.

    Edit: weiterer Lesevorschlag ist std::mem_fn



  • 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.


Log in to reply