C++ Kurs

Wenn fertig, bitte Fenster schließen

Funktionszeiger

Ok, begeben wir uns in die Tiefen der C++ Programmierung! In einem Funktionszeiger können, wie unschwer zu erraten ist, Adressen von Funktionen abgelegt werden.

Definition eines Funktionszeigers

Sehen wir uns zunächst die Definition eines Funktionszeigers an. Die Definition eines Funktionszeigers gleicht im Prinzip der Deklaration einer Funktion, deren Adresse später im Zeiger abgelegt werden soll. Nur dass jetzt anstelle des Funktionsnamens der Name des Funktionszeigers innerhalb einer Klammer steht. Damit kann ein Funktionszeiger auch nur die Adressen von Funktionen aufnehmen, die im Returntyp und in der Anzahl und Art der Parameter mit der Zeigerdefinition übereinstimmen.


// Zeiger auf Funktionen vom Typ
//     void Func();

void (*pfnFunc1)();
// Zeiger auf Funktionen vom Typ
//     short Func(short, char*);

short (*pfnFunc2)(short, char*);

Im Funktionszeiger pfnFunc1 können nur Adressen von Funktionen ablegt werden, die keine Parameter besitzen und auch keinen Returnwert liefern. Der Zeiger pfnFunc2 hingegen kann nur Adressen von Funktionen aufnehmen, die als ersten Parameter einen short-Wert und als zweiten Parameter einen char-Zeiger erwarten. Zusätzlich müssen die Funktionen auch noch einen short-Wert als Returnwert besitzen.

Bilden einer Funktionsadresse

Nach dem der Funktionszeiger definiert ist, kann ihm die Adresse einer entsprechenden Funktion zugewiesen werden. Um die Adresse einer Funktion zu erhalten wird einfach der Name der entsprechenden Funktion angegeben, d.h. es darf hier kein Adressoperator & stehen. Beachten Sie aber bitte, dass Sie dem Zeiger auch nur Adressen von solchen Funktionen zuweisen, die im Returntyp und den Parametern mit dem Zeigertyp übereinstimmen! So würde im nachfolgenden Beispiel die Zuweisung der Adresse der Funktion DoAnything(...) zum Zeiger pfnFunc1 einen Übersetzungsfehler erzeugen.


// Funktionsdeklarationen
void DoSomething();
short DoAnything(short, char*);
// Zeigerdefinition
void (*pfnFunc1)();
short (*pfnFunc2)(short, char*);
// Adresse der Funktion zuweisen
pfnFunc1 = DoSomething;
pfnFunc2 = DoAnything; 

Funktionsaufruf über Funktionszeiger

So, bleibt zum Schluss nur noch die Frage offen, wie die Funktion aufgerufen wird, deren Adresse im Zeiger abgelegt ist. Wie Sie bestimmt noch wissen erfolgt der Zugriff auf Speicherstellen über Zeiger durch den Dereferenzierungsoperator *. Und genauso geht's auch beim Aufruf von Funktionen über Funktionszeiger. Nur muss der dereferenzierte Funktionszeiger jetzt innerhalb einer Klammer stehen. Erhält die aufzurufende Funktion noch Parameter, so sind diese, wie bei einem 'normalen' Funktionsaufruf, in einer weiteren Klammer anzugeben.


// Zeigerdefinition
void (*pfnFunc1)();
short (*pfnFunc2)(short, char*);
...
// Funktionsaufrufe
(*pfnFunc1)();
short nErg = (*pfnFunc2)(var, text);

Beispiel:

Über den Zeiger pfnState werden die Funktionen State1(...), State2(...) und State3(...) nacheinander aufgerufen. Dazu wird zunächst in der main() Funktion der Zeiger auf die erste aufzurufende Funktion State1(...) gesetzt. In der nachfolgenden while-Schleife wird dann so lange die im Zeiger abgelegte Funktion aufgerufen, bis der Zeiger den Wert NULL enthält. Welche Funktion hierbei aufgerufen wird, wird durch die vorher ausgeführte Funktion festgelegt. So lädt z.B. State1(...) als nächste auszuführende Funktion die Adresse der Funktion State2(...) in den Funktionszeiger. Die Funktion State3(...) veranlasst schließlich den Abbruch der while-Schleife, in dem abhängig von einer Bedingung der Wert NULL in den Zeiger geschrieben wird.

Zustand 1: Zähler=1
Zustand 2: Zähler=2
Zustand 3: Zähler=3
Zustand 1: Zähler=4
Zustand 2: Zähler=5
Zustand 3: Zähler=6


// Beispiel zur Funktionszeiger
// Dateien einbinden

#include <iostream>

using std::cout;
using std::endl;

// Deklaration der Zustandsfunktionen
void State1(short&);
void State2(short&);
void State3(short&);
// Funktionszeiger definieren
void (*pfnState)(short&);

// main() Funktion
int main ()
{
   short counter = 1;
   // Funktionszeiger auf 1. Zustand
   pfnState = State1;

   // Nun alle Zustände durchlaufen
   do
   {
      // Zustandsfunktion aufrufen
      (*pfnState)(counter);
   } while (pfnState != NULL);
}

// Funktion für Zustand 1
void State1(short& var)
{
   cout << "Zustand 1: Zähler=" << var << endl;
   var++;
   // Nächsten Zustand im Funktionszeiger ablegen
   pfnState = State2;
}
// Funktion für Zustand 2
void State2(short& var)
{
   cout << "Zustand 2: Zähler=" << var << endl;
   var++;
   // Nächsten Zustand im Funktionszeiger ablegen
   pfnState = State3;
}
// Funktion für Zustand 3
void State3(short& var)
{
   cout << "Zustand 3: Zähler=" << var << endl;
   // Falls übergebener Parameter kleiner 4 Zustand wieder
   // auf 1 setzen sonst kein weiterer Zustand

   if (var < 4)
      pfnState = State1;
   else
      pfnState = NULL;
   var++;
}