Objektorientierung mit Funktionspointern

Den Objekttypen im Objekt zu speichern ist eine legitime Lösung um zur Laufzeit zu entscheiden, welche Funktion gerufen werden soll. Wenn das Programm erweitert wird, müssen jedoch alle Stellen gesucht werden, wo auf den Objekttypen abgefragt wird.

Also suchen wir eine neue Möglichkeit: Funktionspointer

class Tier
{
public:
  char Name[64];
  int  Fellfarbe;
  int  KrallenLaenge;
  int  AnzahlBeine;
 
  inline void GibNamenAus( void ) { printf( "Ich heiße %s\n", Name ); }
 
  void (*GibLaut)( void );
 
  Tier( void (*gibLaut)(void) ) : GibLaut( gibLaut ) {} 
};

Das void in der Parameterliste ist eigentlich überflüssig und wird auch gerne weggelassen. Hier trage ich es ein, weil es zusätzlich darauf hinweist, dass hier eine Funktion ohne Parameter übergeben wird.

Nun können wir jeder Instanz von Tier eine Funktion mitgeben, mit der sie GibLaut() ausgeben kann. Entsprechend können wir die Funktion im Konstruktor belegen:

class Katze : public Tier
{
  static void InternGibLaut( void );
 
public:
  int   GefangeneVoegel;
 
  Katze() : Tier( Katze::InternGibLaut ) {} 
};
...
void Katze::InternGibLaut()
{
  printf( "Miau!\n" );
}

Nun kann man GibLaut() mit einem Tier rufen und landet in der Funktion, die der Konstruktor der jeweiligen Instanz vorbelegt hat.

Das bedeutet, dass wir keine Enum mehr benötigen, die festlegt, um welches Objekt es sich handelt und auch nicht mehr in Abhängigkeit der Enum in den einzelnen Funktionen unterschiedlich entscheiden müssen. Wir rufen mit GibLaut() automatisch die richtige Funktion auf.

Ebenfalls lässt sich die Funktion jederzeit für jedes Objekt austauschen. Das ist also wirklich objektorientiert und nicht nur datentyporientiert.