Funktionszeiger



  • Erzähl mir mal einer, warum das:

    void (*func)();
    void something() { };
    
    void main()
    {   func = something;
    };
    

    aber nicht das:

    class FOO
    {       void (*func)();
        public:
            FOO()
            {   func = something;
            };
            void    something() { };
    };
    
    void main()
    {   FOO argh;      
    };
    

    geht. Ich hab echt keine Plan...



  • Ich hab echt keine Plan...

    Dann besorg dir doch einen 😃
    Ein Blick in unsere FAQs und eine kleine Suche sollte z.B. helfen.

    Kurz:
    Methodenzeiger und Funktionszeiger sind zwei völlig verschiedene und inkompatible Konzepte.
    Im Typ eines Methodenzeigers ist imm er auch die entsprechende Klasse enthalten.
    Allgemein sieht die Deklaration so aus:

    Rückgabewert (KlassenName::*)(ParameterListe);
    

    Ein Aufruf einer Methode über einen Methodenzeiger funktioniert nur in Verbindung mit einem Objekt.

    class Foo
    {
    public:
        void Func() {}
    };
    
    int main()
    {
        void (Foo::*pMemFun)() = &Foo::Func;  // das & ist zwingend erforderlich!
        Foo f;
        (f.*pMemFun)(); // Die Klammern sind zwingend erforderlich.
                        // Aufruf nur in Verbindung mit einem Objekt möglich!
    }
    

    [ Dieser Beitrag wurde am 17.03.2003 um 20:29 Uhr von HumeSikkins editiert. ]



  • Danke, für die rasche und ausführliche Hilfe.



  • http://www.function-pointer.org

    [ Dieser Beitrag wurde am 17.03.2003 um 20:43 Uhr von Lars editiert. ]



  • Hallo!

    Ich verstehe leider nicht wie das nun ist bei Methodenzeigern bei Klassen:
    Und zwar ist im Beispiel oben der Zeiger auf die Funktion _außerhalb_ der klasse. Wie verhältes sich nun wenn der Zeiger INNERHALB der klasse ist?

    /*
     * 
     * Projekt     :  *** NEURONALE NETZE ***
     * 
     */
    
    #include <stdlib.h>  // wegen: NULL
    #include <vector>    // vielleicht vector<> statt ARRAYs
    
    #ifndef __CNEURON_H
    #define __CNEURON_H
    
    using namespace std;
    
    // Datentyp, mit dem man angibt, welche Aktivierungsfunktion man wählt
    typedef enum { linear = 1, quadr, cubic, cut, signum, sigmoid, gauss } TFunctions;
    // Datentyp, mit dem man angibt, wie die Gewichtung festgelegt werden soll
    typedef enum { standard = 1, constant, randomized } TOmegas;
    
    // Klasse CNeuron
    // - Die Klasse CNeuralNet benutzt CNeuron.
    class CNeuron
    {
        private:
        //
        double   output;           // Ausgang des Neurons
        double*  omegas;           // Gewichtungen der Eingaenge
        vector< CNeuron* > inputs; // Array aus Zeigern auf die Outputs der Vorgaenger-Neuronen
        unsigned long numinputs;   // Anzahl der Eingaenge / Vorgaenger-Neuronen
        double   limit;            // Schwellwert
        double   (*f)  ( double ); // Zeiger auf die Aktivierungsfunktion
    
        // Aktivierungsfunktionen
        double f_linear( double z ) { return z; }
        double f_quadr ( double z ) { return z*z; }
        double f_cubic ( double z ) { return z*z*z; }
        double f_cut   ( double z ) { return ( z >= limit ? 1.0 : 0.0 ); }
    
        public:
        // Konstruktoren
        // Standardkonstruktor ohne Parameter
        CNeuron()
        {
            output = 0.0;  // Output wird auf 0 gesetzt
            limit  = 0.5;  // Die Schwelle wird auf 1/2 festgesetzt als Standard
            omegas = NULL; // Keine Gewichtungen festlegen
            numinputs = 0; // da keine Vorgaenger festgelegt sind, wird deren Anzahl auf 0 gesetzt
            this->setFunction( linear );  // Standard-Aktivierungsfunktion ist linear
        }
        // Konstruktor, mit ganz vielen Parametern
        CNeuron( vector< CNeuron* > in, double w[] = NULL, TFunctions func = linear, double sig = 0.5 )
        {
            // Zuerst wird der Standard-Konstruktor aufgerufen
            CNeuron();
            // Hier wird das Neuronen mit seinen Eingaengen/Vorgaengern verknuepft
            if( !in.empty() )
            {
                // Anzahl der Eingaenge/Vorgaenger wird bestimmt und gespeichert
                numinputs = sizeof(in) / sizeof(in[0]);
                inputs.clear();
                // Falls eine Gewichtung angegeben ist ...
                if( w != NULL )
                    for( register unsigned long i = 0; i < numinputs; i++ )
                    {
                         inputs.push_back( in[ i ] );
                         this->omegas[ i ] = w [ i ];
                    }
                // Falls keine Gewichtung angegeben ist ...
                else
                {
                    for( register unsigned long i = 0; i < numinputs; i++ )
                         inputs.push_back( in[ i ] );
                    ;
                }
            }
            this->setFunction( func );
            this->limit = sig ; // Legt SIGMA fest ~ ~ ~
        }
        // Destruktor
        ~CNeuron()
        {
            inputs.clear();
            /*
             * Löscht alle Vorgaenger-Neuronen. 
             * Dies wiederum bewirkt, dass diese Neuronen ihre Vorgaenger löschen, usw.
             * Ergibt eine "Kettenreaktion" von hinten nach vorne.
             * Evtl. Problem: Bereits gelöschte Neuronen sollen nochmal gelöscht werden ?
             */
        }
    
        // -----------------------------------------------------
        // ******************** FUNKTIONEN *********************
        // -----------------------------------------------------
    
        // Einstellungen
    
        void setInputs( vector< CNeuron* > in )
        {
    
        }
    
        void setOmegas( int om = 1, double w = 1.0 )
        {
             switch( om )
             {
               case standard   :     if( omegas != NULL )   delete[] omegas;
                                     omegas = new double[ numinputs ];
                                     w = 1.0 / numinputs;
                                     for( register unsigned long i = 0; i < numinputs; i++ )
                                     {
                                          omegas[ i ] = w;
                                     }
                                     break;
               case constant   :     if( omegas != NULL )   delete[] omegas;
                                     omegas = new double[ numinputs ];
                                     for( register unsigned long i = 0; i < numinputs; i++ )
                                     {
                                          omegas[ i ] = w;
                                     }
                                     break;
               case randomized :     if( omegas != NULL )   delete[] omegas;
                                     omegas = new double[ numinputs ];
                                     for( register unsigned long i = 0; i < numinputs; i++ )
                                     {
                                          omegas[ i ] = rand();
                                     }
                                     break;
    
               default:              break;
             }
        }
    
        void setFunction( TFunctions func = linear )
        {
             switch( func )
             {
                   case linear : f = &CNeuron::f_linear; break;
                   case quadr  : f = &CNeuron::f_quadr;  break;
                   case cubic  : f = &CNeuron::f_cubic;  break;
                   case cut    : f = &CNeuron::f_cut;    break;
             }
        }
    
        // Getter / Setter - Methoden
    
        double getOutput() { return output; }
    
        // Berechnungen
    
        double evaluate()
        {
            double sum = 0.0;
            for( register unsigned long i = 0; i < numinputs; i++ )
                 sum += omegas[i] * inputs.at( i )->getOutput();
            return ( output = f( sum ) );
        }
    
    };
    
    #endif
    

    in diesem quellcode, ist die wesentliche Methode "setFunction"
    dabei gibt mir bei der obigen implementierung der compiler folgende fehlermeldung:

    141 C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Programmierung\C\CNeuralNet\CNeuron.h
    cannot convert `double (CNeuron::*)(double)' to `double

    weiß jemand rat?
    ich habe schon zig tutorials & threads durchgelesen... aber nichts hat mich wirklich weitergebracht. mein aktueller wissensstand ist eben das was ich im code oben geschrieben habe. Ich hab auch schon anderes probiert, z.b. ohne "&" oder ohne "&CNeuron::"... nix hilft. aber dann kommen auch andere fehlermeldungen. wenn ich nur schreibe "f = f_linear;" dann heißt es er konnte f_linear keiner funktion zuordne, er würde aber vermuten, dass CNeuron::f_linear gemeint ist.

    _ h i l f e _

    verzweifelter hiroki, der endlich weiterkommen will in seinem programm und nicht an solch einer "kleinigkeit" festhängen will . . .

    DANKE

    PS:
    wäre es vielleicht möglich, dass mir einer einfach sagt was an den vier zeilen der methode "setFunction" falsch ist und es vielleicht korrigiert?

    D A N K E

    [ Dieser Beitrag wurde am 18.03.2003 um 19:04 Uhr von hiroki editiert. ]



  • lies mal was Hume geschrieben hat:

    ein methoden zeiger ist etwas anderes als ein funktionszeiger.

    bei einem methodenzeiger muss nämlich noch irgendwo this übergeben werden!


Log in to reply