Funktionspointer - Function Pointer



  • Hi,

    ich hab ein Verständnisproblem mit den Function Pointern. Vorweg, ja ich habe mir schon fast alle Beiträge hier im Forum angeschaut.

    Kurz und knapp, hier ist der Code und was er an welcher Stelle machen soll:

    class A
    {
    public:
    	void sayHello(){ std::cout << "Hello from A\n"; }
    	void sayAnotherHello() { std::cout << "Another hello from A\n"; }
    };
    
    int main()
    {
    	A a;
    	void (*helloFunc)() = // ? Hier will ich sagen das helloFunc auf a.sayHello() zeigt
    	helloFunc();
    	helloFunc = // ? Hier will ich sagen das helloFunc auf a.sayAnotherHello() zeigt
    	helloFunc();
    }
    

    Ich benutze Visual Studio 8. Vielen Dank im Vorraus.





  • Ehm das ist jetzt nicht ganz so einfach. Das ist kein normaler Funktionszeiger mehr.
    Die Funktionssignatur:

    typedef void (*fnHello)()
    

    gehört bsw. zu einer Funktion wie:

    void foo()
    {
        std::cout << "Hello" << std::endl;
    }
    
    int main()
    {
        fnHello func = &foo;
        func();
    }
    

    ... D.h. die Funktion liegt nicht in einer Klasse/Struct. Sozusagen ist das ein "C-Style" Funktionszeiger 😛

    Scheinbar willst du jetzt aber ein Funktionszeiger auf eine Memberfunktion haben? Geht auch! Da muss die Signatur der Funktion aber geändert werden!

    typedef void (A::*fnHello)() /*const*/
    

    ...

    void A::foo() /*const*/
    {
        std::cout << "Hallo" << std::endl;
    }
    
    int main()
    {
        fnHello func = &A::foo;
        A obj;
        (obj.*func)();
    }
    

    Eine Funktionszeiger auf eine Memberfunktion braucht aber immer ein Objekt (es sei den die Funktion ist static), da einer Memberfunktion IMMER(wenn nicht static) einen this-Zeiger übergeben bekommt.

    =>

    class A
    {
    public:
        void foo() const { std::cout << "foo()" << std::endl; }
        void bar() const { std::cout << "bar()" << std::endl; }
    };
    
    typedef void (A::*fnCall)() const;
    
    int main()
    {
        A obj;
        fnCall say = &A::foo;
        (obj.*say)();
        say = &A::bar;
        (obj.*say)();
    }
    

    🙂



  • (D)Evil ich danke dir!

    Nachtrag:

    Wie kann ich jetzt die Methode übergeben und in einer anderen Methode aufrufen? Dazu muss ich doch das Objekt und die Methode dann übergeben?

    void scream(void* obj, void (*fnHello)())
    .
    .
    .
    a.scream(&a, &A::sayAnotherHello); // geht nicht
    

    Wo ist mein Denkfehler?



  • Du scheinst Methoden und Methodenpointer trotzdem noch nicht verstanden zu haben.
    Wenn du willst, daß deine Methode A::scream sowohl ein Objekt als auch eine Methode (als Methodenzeiger) übergeben bekommen soll, dann mußt du auch die Parameter dementsprechend deklarieren.
    Wenn bei dir zusätzlich das übergebene Objekt immer gleich dem aktuellen Objekt (bei dir heißt die Variable 'a') ist, dann kannst du auch diesen Parameter einsparen und intern in der Methode dann 'this' verwenden.
    Code gebe ich dir jetzt extra nicht, damit du es selbst herausfindest.
    Übung macht den Meister!



  • Guck dir mal nochmal an was ich oben geschrieben habe:

    typedef void (A::*fnCall)() const;
    

    ... dann guck dir mal deine Funktion an. Dazu solltest du beachten, dass bei einem void-Zeiger sämtliche Typeninformationen verloren gehen!

    template<typename T>
    struct scream
    {
        typedef void (T::*fnFunc)() const;
        static void call(const T& obj, fnFunc ptr) const;
        {    (obj.*ptr)(); }
    };
    
    class bar
    {
    public:
        void foo() const;
    };
    
    int main()
    {
        bar _inst;
        scream<bar>::call(_inst, &bar::foo);
    }
    

    :....



  • (D)Evil schrieb:

    template<typename T>
    struct scream
    {
        typedef void (T::*fnFunc)() const;
        void call(const T& obj, fnFunc ptr) const;
        {    (obj.*ptr)(); }
    };
    
    [...]
        scream<bar>::call(_inst, &bar::foo); [...]
    

    fehlt da nicht ein static? 😉



  • sorry für die späte Antwort, danke für eure Hilfe



  • hi,

    sorry das ganze ist schon sehr alt, aber ich hab ne frage zu dem was Checker&Murckser schrieb.
    Er meinte das ein "static" fehler würde, ich konnte nur leider nicht rausfinden wo es hin kommt.

    könnte ihr mir bitte helfen?


  • Mod

    crischan schrieb:

    hi,

    sorry das ganze ist schon sehr alt, aber ich hab ne frage zu dem was Checker&Murckser schrieb.
    Er meinte das ein "static" fehler würde, ich konnte nur leider nicht rausfinden wo es hin kommt.

    könnte ihr mir bitte helfen?

    (D)Evil hat seinen Code doch schon vor 8 Jahren entsprechend korrigiert...



  • ah jau,

    jetzt wo du es sagt sehe ich es auch^^

    aber warum bekomm ich den bei

    scream<bar>::call(_inst, &bar::foo);
    

    den fehler code C2272 : 'call': Modifizierer bei statischen Memberfunktionen nicht zulässig?

    Oder eine andere frage
    Wie kann ich "void (CLASS::)()" zu "void ()()" konvertieren?
    Geht das überhaupt?


  • Mod

    crischan schrieb:

    aber warum bekomm ich den bei

    scream<bar>::call(_inst, &bar::foo);
    

    den fehler code C2272 : 'call': Modifizierer bei statischen Memberfunktionen nicht zulässig?

    Weil das const nach dem Einfügen des static hätte entfernt werden müssen. Und natürlich ebenso das Semikolon, falls du da nicht selber drauf gekommen wärst.

    Oder eine andere frage
    Wie kann ich "void (CLASS::)()" zu "void ()()" konvertieren?
    Geht das überhaupt?

    Kann es sein, dass dies deine eigentliche Frage ist und es nicht nötig gewesen wäre, die Toten zu stören?

    Die Antwort ist: Mit reinterpret_cast.
    Und ich hoffe, dass bei dir angesichts dieser Antwort alle Alarmglocken läuten. Denn es heißt, dass die Frage keinen Sinn macht.

    Kann es sein, dass du std::bind suchst? Ich rate nämlich mal, dass dein eigentliches Problem (nach dem du gleich in einem neuen Thread hättest fragen sollen) ist, dass du eine Schnittstelle hast, die einen void(*)() erwartet und du an diese Schnittstelle eine Memberfunktion eine bestimmten Objekts übergeben möchtest.



  • ich hab nach einer lösung für mein problem gesucht und auf den ersten blick sah es nach der richtigen lösung aus

    von bind hab ich schon gelesen, war mir aber zu umständlich

    reinterpret_cast hört sich gut an, dazu werde ich gleich mal schlau machen

    und nochmal sorry das ich den alten Thread aufgewärmt hab


  • Mod

    crischan schrieb:

    von bind hab ich schon gelesen, war mir aber zu umständlich

    bind soll umständlich sein?

    reinterpret_cast hört sich gut an, dazu werde ich gleich mal schlau machen

    Wozu fragst du überhaupt, wenn du die Antworten nicht liest? reinterpret_cast beantwortet deine (schlecht gestellte) Frage, aber es hört sich garantiert nicht gut an!



  • das was ich über bind gelesen hab, hab ich ehrlich gesagt nicht wirklich verstanden, bin noch nicht lange bei c++ und manches kommt mir manchmal etwas spanisch vor

    aber vllt kannst du mir erklären wie das mit bind läuft

    Ich will einen function aus einer klasse zu einer anderen function in einer klasse weiter geben und diese function speicher dann diesen zeiger in seiner klasse. hoffe ich hab das so richtig erklärt


  • Mod

    Die Beschreibung ist zu ungenau, um dir vernünftig helfen zu können. Am besten machst du mal einen neuen Thread mit einer brauchbaren Beschreibung deines Problems und einer Erklärung, wobei du Schwierigkeiten hast. So, wie du es gleich hattest machen sollen.


Anmelden zum Antworten