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)() ) : GibLaut( gibLaut ) {} };
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.