Ist eine Member-Function als Funktionsparameter zulässig ???



  • Hallo,
    wenn ich folgenden Code compiliere, meckert der Compiler:

    class A {
    public:
       void f() { /* mach was */}
       void g() { /* mach was anderes */ }
    };
    
    class B {
    public:
       B () {foo (a.f);} /* <== 
          error: no matching  function for call  to 'B::foo(<unresolved overloaded             
         function type>)'
         note: candidates are: void B::foo(void (*)()) */
    private:
       void foo (void x()) {x();}
       A a;
    };
    
    int main () {
       B b;
       return 0;
    }
    

    Wenn ich im B-Konstruktor statt der Member-Funktion a.f eine globale Funktion h als Parameter uebergebe, dann kompilert das Programm tadellos:

    class A {
    public:
       void f() { /* mach was */}
       void g() { /* mach was anderes */ }
    };
    
    void h () {}
    
    class B {
    public:
       B () { foo (h);}
    private:
       void foo (void x()) {x();}
       A a;
    };
    
    int main () {
       B b;
       return 0;
    }
    

    Woran liegt es ?? a.f ist doch innerhalb der Klasse B sichtbar. Gibt es irgendeine Einschraenkung, dass Funktionen als Parameter keine Member-Funktionen sein duerfen ?



  • Ein Zeiger auf eine Memberfunktion ist was anderes als ein Funktionszeiger.

    Ich glaube du würdest mit boost::function am glücklichsten werden.



  • Methoden sind keine Funktionszeiger, weil an ihnen noch ein this-Objekt hängen muss, um aufgerufen zu werden. Sprich der Empfänger braucht die Information, welche Methode gewünscht ist (schreibt sich &A::f), und die Information, welches Objekt das this-Objekt ist (in diesem Fall a). Das sind mindestens zwei Informationen, die so in einen Funktionszeiger nicht hineinpassen.

    Am kurzen Beispiel sieht das so aus:

    typedef void (A::*funcptr)(); // nur weniger Schreibarbeit
    
    void foo(A& objekt, funcptr funktion)
    {
        objekt.*funktion();
    }
    
    foo(a, &A::f);
    


  • Danke fuer die Hinweise !
    @TheKenny: Die boost::function schaue ich mir an.
    @LordJaxom: Ich habe Deine Loesung in mein Bsp. eingebaut, bekomme aber ein error. Leider bin ich noch nicht so sattelfest, weiss nicht, wie ich das beheben soll.

    class A {
    public:
       void f() { /* mach was */}
       void g() { /* mach was anderes */ }
    };
    
    class B {
    public:
       B () { foo (a, &A::f);} 
    private:
       typedef void (A::*funcptr)(); // nur weniger Schreibarbeit
       void foo(A& objekt, funcptr funktion) {objekt.*funktion();}   /*<== error: must use '.*' or '->*' to call pointer-to-member function in 'funktion (...)'*/
    
       A a;
    };
    
    int main () {
       B b;
       return 0;
    }
    


  • du hast einfach die operatorenrangfolge vergessen: () geht vor .*

    (object.*funktion)();
    


  • Das war's... es flutscht !
    Uebrigens, die boost::function - Loesung von Kenny laeuft auch und ist ebenfalls kurz & buendig !

    muuuuuuchas gracias, amigos !!!!! 🙂 👍 🕶 👍


Anmelden zum Antworten