Funkionsreferenzen statt Funktionszeigern?



  • warum kann ich keine referenzen auf memberfunktionen haben?



  • class foo_t {
    
        public:
            void bar( ) { }
    };
    
    int main( ) {
    
        void ( foo_t::*static_member_ref )( void ) = &foo_t::bar;
    
        foo_t a;
        ( a.*static_member_ref )( );
    }
    

    Ich schätze, weil man Referenzen nicht (explizit) dereferenzieren kann.

    greetz, Swordfish

    PS: Eine Referenz auf statische Methoden ist möglich.



  • das beispiel versteh ich nicht ganz

    class foo_t {
    
        public:
            void bar( ) { }
    };
    
    int main( ) {
    
        // was ist denn *static_member_ref
        void ( foo_t::*static_member_ref )( void ) = &foo_t::bar;
    
        foo_t a;
        // a hat doch nur bar() als member funktio oder nicht?
        ( a.*static_member_ref )( );
    }
    


  • FreakyBKA schrieb:

    das beispiel versteh ich nicht ganz

    ...
        // was ist denn *static_member_ref
        void ( foo_t::*static_member_ref )( void ) = &foo_t::bar;
    ...
    

    Ist ein ganz normale Variablendeklaration.
    so wie in:

    int i; // Variable vom Typ int
    void (*i)(int); // ... vom Typ "Funktion, mit int als Parameter und void Rückgabe"
    void (C::*i)(int); // ... vom Typ "Memberfunktion der Klasse C, mit int als Parameter und void Rückgabe"
    void (C::*static_member_ref)(void); // ... vom Typ "Memberfunktion der Klasse C, ohne Parameter und void Rückgabe"
    

    Trotzdem stimme ich Dir zu: Ich verstehe nicht, was das mit "Referenz auf eine Memberfunktion" zu tun hat.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Trotzdem stimme ich Dir zu: Ich verstehe nicht, was das mit "Referenz auf eine Memberfunktion" zu tun hat.

    Ich schätze Swordfish wollte auf den Aufruf dieser "Memberfunktionsreferenz" hinaus. Die Operatoren dafür sind .* und ->*, beide implizieren eine Dereferenzierung, und die funktioniert nunmal nur bei Zeigern, nicht bei Referenzen.



  • Simon2 schrieb:

    FreakyBKA schrieb:

    das beispiel versteh ich nicht ganz

    ...
        // was ist denn *static_member_ref
        void ( foo_t::*static_member_ref )( void ) = &foo_t::bar;
    ...
    

    Ist ein ganz normale Variablendeklaration.

    wieso kann ich denn außerhalb der klasse neue member deklarieren? das hab ich noch nirgendwo gesehen.



  • naja das ginge dann wie beim normalen "dereferenzeieren" von referenzen durch Weglassen des *-operators:

    typedef int (C::mem_fun_ptr*)(int);
    typedef int (C::mem_fun_ref&)(int);
    
    class C {
    public:
      int foo(int);  
    };
    
    int main() {
      mem_fun_ptr mfp = &C::foo;
      mem_fun_ref mfr = C::foo;
    
      C c;
      int i = c.*mfp(14);
      int j = c.mfr(15);
    }
    

    also ganz analog zu normalen Zeigern/referenzen - aber geht wohl nicht 😉



  • pumuckl schrieb:

    also ganz analog zu normalen Zeigern/referenzen - aber geht wohl nicht 😉

    Würde mir als Compiler schwerfallen das von einem Methodenaufruf (mfr ist eine Memberfunktion) oder Funktionszeigeraufruf (mfr ist ein public Member vom Typ Funktionszeiger) zu unterscheiden 😉

    Wäre wohl technisch zu aufwendig gewesen.



  • FreakyBKA schrieb:

    ...

    ...
        // was ist denn *static_member_ref
        void ( foo_t::*static_member_ref )( void ) = &foo_t::bar;
    ...
    

    Ist ein ganz normale Variablendeklaration.

    wieso kann ich denn außerhalb der klasse neue member deklarieren? ...

    😕 Tust Du auch gar nicht und das habe ich auch nicht behauptet.
    Nochmal zum genau lesen: Es ist eine Deklaration einer Variablen eines Typs.

    In diesem Beispiel: Du hast eine Variable namens "static_member_ref" (könnte auch "Hugo" heißen) und diese hat den Typ "Zeiger auf void-void-Memberfunktion der Klasse foot_t".
    Die spannenden Frage ist doch: Was kann man mit einer solchen Variable anfangen ?

    Antwort: Alles, was man auch sonst mit einem (Funktions)-Zeiger machen kann: Auf verschiedene "Ziele" zeigen und per Dereferenzierung auf diese "Ziele" zugreifen.

    Natürlich wird (wie bei jedem Zeiger) bei "... auf zeigen lassen.." (= Adresse zuweisen) geprüft, ob der Typ stimmt; sonst meckert der Compiler.

    struct C {
       void a();
       void b();
       int c();
       void c(int);
    };
    
    struct D {
       void a();
    };
    
    int i1, i2;
    double d;
    
    int main() {
       C c;
       void (C::*mem_fun_ptr)(void); // Zeiger-variable... analog zu:
       int* i_ptr;
    
       mem_fun_ptr = &C::a; // OK, Typ passt ... analog zu:
       i_ptr = &i1;
       (c.*mem_fun_ptr)(); // ruft c.a() auf ... analog zu:
       *i_ptr = 1;         // ... i1 wird gesetzt
    
       mem_fun_ptr = &C::b; // OK, Typ passt ... analog zu:
       i_ptr = &i2;
       (c.*mem_fun_ptr)(); // ruft c.b() auf ... analog zu:
       *i_ptr = 2;         // ... i2 wird gesetzt
    
       mem_fun_ptr = &C::c; // ERROR: Typ passt nicht ... 
       mem_fun_ptr = &D::a; // ERROR: Typ passt nicht ... analog zu:
       i_ptr = &d;
    
    ...
    

    Gruß,

    Simon2.



  • LordJaxom schrieb:

    Simon2 schrieb:

    Trotzdem stimme ich Dir zu: Ich verstehe nicht, was das mit "Referenz auf eine Memberfunktion" zu tun hat.

    Ich schätze Swordfish wollte auf den Aufruf dieser "Memberfunktionsreferenz" hinaus. Die Operatoren dafür sind .* und ->*, beide implizieren eine Dereferenzierung, und die funktioniert nunmal nur bei Zeigern, nicht bei Referenzen.

    Cool, es gibt Leute, die mich verstehen 😃

    Mich würd' aber interessieren, ob es noch einen anderen Grund gibt, warum es keine "Methodenreferenzen" geben kann. Von einem ungültigem ::& konstrukt einmal abgesehen.

    greetz, Swordfish


Anmelden zum Antworten