Function-Pointer , und Class Method



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

    ProgressCallbackFunc

    1. Du hast dich höchstwahrscheinlich im Unterforum geirrt, oder hat das irgendwie einen Zusammenhang zu C++/CLI?

    2. Das Hauptproblem ist, dass ein Function-Pointer und ein Member Function-Pointer nicht dasselbe sind (siehe hier: https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types). Benutze einfach std::function<..>, damit machst du dir das Leben leichter.



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

    @theta : Ja tut mir leid, hab das falsche Unterforum gewählt. Ok dachte funktionptr und member -funktionptr machen keinen unterschied . d.h. mit dem std::function kann ich sowas übergreifen machen? Kannst du mir das anhand meines Beispiels mit dem std:Function zeigen?



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

    d.h. mit dem std::function kann ich sowas übergreifen machen?

    Nein, natürlich nicht. Das habe ich nur geschrieben, um dich zu verwirren.

    Aber ernsthaft: Ja, das kannst du. Und dir wird ein weiteres "Problem" auffallen. Denn eine nicht-statische Memberfunktion muss auf einem Objekt aufgerufen werden - im Beispiel von dir gibt es beim Aufruf aber kein Objekt, auf dem die Memberfunktion aufgerufen werden kann. Aber auch das kann man mit std::function<..> einfach lösen. Schau dir auch mal std::bind(..) an. Und probier auch die Idee von Schlangenmensch mit den Lambdas aus.



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


Anmelden zum Antworten