Basiskonstruktoren rufen

Bisher haben unsere Klassen noch keine Konstruktoren. Das wollen wir nun nachholen:

class Tier
{
public:
  char Name[64];
  int  Fellfarbe;
  int  KrallenLaenge;
  int  AnzahlBeine;
 
  inline void GibNamenAus( void ) { printf( "Ich heiße %s\n", Name ); }
 
  Tier( char const * name, int fellfarbe, int krallenLaenge, int beine )
    : Fellfarbe( fellfarbe )
    , KrallenLaenge( krallenLaenge )
    , AnzahlBeine( beine )
  {
    int laenge = strlen( name );
    if( laenge > 63 ) laenge = 63;
 
    memcpy( Name, name, laenge );
    Name[ laenge ] = '\0';
  } 
};

Wenn wir nun einen Hund „erstellen“, so muss erst der Teil der Instanz initialisiert, der das Tier beschreibt. Erst dann wird die Spezialisierung des Tiers initialisiert: der Hund.

Das Tier ist wie eine Membervariable aus der Sicht des Konstruktors und muss über die Initialisierungsliste initialisiert werden. Diese Variable hat jedoch keinen Namen, sondern wird über den Namen des Datentyps angesprochen.

In unserem Fall können wir den Konstruktor so schreiben, dass wir einige Informationen bereits im Konstruktor des Hundes kennen und gar nicht abfragen müssen. So gehen wir davon aus, dass Hunde und Katzen jeweils vier Beine und Amseln zwei Beine haben. Dies müssen wir beim Erstellen eines Hundes dann nicht mehr explizit angeben:

class Hund : public Tier
{
public:
  int  GefangeneKatzen;
 
  inline void GibLaut( void ) { printf( "Wau!\n"; }
 
  Hund( char const * name, int fellfarbe, int krallenLaenge, int gefangeneKatzen )
  : Tier( name, fellfarbe, krallenLaenge, 4 /* <- Beine */ )  // Basiskonstruktor für die Klasse Tier
  , GefangeneKatzen( gefangeneKatzen )
  {}
};

Entsprechendes gilt für die Konstruktoren für Katze und Amsel.

Nun können wir einen Hund über den Konstruktor erzeugen:

int main( void )
{
  Hund hund( "Bello", 1, 5, 10 ); // Bello hat die 1. Farbe, 5mm Krallenlänge und 10 gefangene Katzen
 
  hund.GibLaut();     // Methode Hund::GibLaut() rufen
  hund.GibNameAus();  // Methode Tier::GibNameAus() rufen
}