Funktionen aus der Basisklasse überschreiben

Für dieses Kapitel schauen wir uns kurz noch einmal unsere Tier-Klassen aus der Einführung in die Vererbungslehre an und erweitern die Hund-Klasse um die Funktion GibNamenAus( char const * familyName ):

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

Nun wollen wir das folgende Programm ausführen:

int main( void )
{
  Hund harry( "Harry" );
  
  harry.GibNamenAus();

  return EXIT_SUCCESS;
}

Wie immer ist der Code gekürzt, so fehlen z.B. die Konstruktoren. Den vollständigen Code gibt es hier.

Der Compiler meldet hierfür:

withoutusing.cpp: In function ‘int main()’:
withoutusing.cpp:50: error: no matching function for call to ‘Hund::GibNamenAus()’
withoutusing.cpp:34: note: candidates are: void Hund::GibNamenAus(const char*)

Er kennt also die Funktion Hund::GibNamenAus() ohne Parameter nicht mehr. Die Methode wurde mit void GibNamenAus( char const * familyName ) überladen. Wird eine Methode überladen, so werden alle bereits bekannten Möglichkeiten aus dem Namensraum entfernt. Darum kennt der Namensraum der Klasse Hund die Methode GibLaut() ohne Parameter nicht mehr.

explizite Nennung des Namensraums

Wir wissen bereits, dass vererbte Fähigkeiten nicht verloren gehen, wir können also darauf aufmerksam machen, dass es die gewünschte Methode im Namensraum der Basisklasse Tier gibt:

int main( void )
{
  Hund harry( "Harry" );
  
  harry.Tier::GibNamenAus();

  return EXIT_SUCCESS;
}

Das funktioniert. Häufig ist das aber gar nicht der Wunsch des Entwicklers, oftmals möchte man eine weitere Methode den vorhandenen hinzufügen, so dass man die vererbten Funktionen weiterhin auch aus dem Namensraum der Klasse Hund rufen kann, ohne den Namensraum der Klasse Tier voranzustellen.

Methoden nicht aus dem Namensraum entfernen

Hierfür verwendet man das Schlüsselwort using.

using gilt immer für alle geerbten Methoden der gewählten Basisklasse, daher werden auch keine Rückgabewerte oder Parameter angegeben:

class Hund : public Tier
{
public:
  int  GefangeneKatzen;
 
  inline void GibLaut( void ) { printf( "Wau!\n"; }
 
  using Tier::GibNamenAus; 
  inline void GibNamenAus( char const * familyName ) 
  { 
    printf( "Ich heiße %s %s\n", Name, familyName ); 
  }
};

So lässt sich nun die Funktion wie gewünscht in beiden Varianten rufen, ohne den Namensraum explizit angeben zu müssen.

Der kompilierfähige Quelltext findet sich hier.