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.
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.
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.