Vererbung Klassen - Vererbung Eine Klasse kann von einer Basisklasse abgeleitet werden Die abgeleitete Klasse erbt die Eigenschaften und Methoden der Basisklasse class derivedClass : [modifier] baseClass { … }; Klassen - Vererbung Eine Ableitung einer Klasse repräsentiert eine IS-A-Relation Eine Membervariable repräsentiert eine HASA-Relation class Vogel : public Tier {… Fluegel myWings_; …} Vogel ist ein Tier und hat Flügel Zugriffsmodifizierer bei abgeleiteten Klassen public: alle Methoden und Eigenschaften der Basisiklasse mit dort definierter Sichtbarkeit weitergereicht private: Methoden und Eigenschaften der Basisklasse von außen nicht mehr aufrufbar protected: Weitere abgeleitete Klassen bekommen den Zugriff auf die Basisklasse Zugriffsmodifizierer bei abgeleiteten Klassen class A { public int a_; } class B : public A { public int b_; } class E : private B { private int e_; } class C : private A { private int c_; } class F : protected C { protected int f_; } class D : protected A { protected int d_; } class G : public D { public int g_; } Vererbung – Konstruktoren Konstruktor der Basisklasse wird vom Konstruktor der abgeleiteten Klasse aufgerufen Implizit -> Standardkonstruktor Explizit mit Parameterübergabe class derivedClass : baseClass { … }; derivedClass::derivedClass(int p1, int p2) : baseClass(p3) { … }; Aufgabe 15: Erben Erstelle eine Klasse mit folgenden Eigenschaften speichert einen Integer-Wert besitzt einen Konstruktor, einen Destruktor und eine Funktion zum Ausgeben des Wertes Konstruktor und Destruktor sollen eine Meldungszeile ausgeben Erstelle eine davon abgeleitete Klasse, die zusätzlich einen, ebenfalls über den Konstruktor zu setzenden Fließkommawert speichert Erstelle eine Variable von der abgeleiteten und eine Variable der Basis-Klasse und rufe die in der Basisklasse definierte Funktion zum Ausgeben des Wertes auf Vererbung - Overriding genau äquivalente Deklaration einer Funktion / Eigenschaft in einer abgeleiteten Klasse ursprüngliche Deklaration in der Basisklasse wird versteckt Aufgabe 16: Erben überschreiben Ändere die in Aufgabe 15 erstellte abgeleitete Klasse dahin gehend ab, dass die geerbte Funktion zum Anzeigen des Wertes überschrieben wird die überschriebene Funktion soll den in der abgeleiteten Klasse gespeicherten Wert ausgeben Vererbung - Overriding Aufruf der versteckten Eigenschaft / Funktion möglich in der Memberfunktion der abgeleiteten Klasse mittels Scope-Operator baseClass::Funktion(); Aufruf von Außen: upcast zur Basisklasse ((baseClass)varDerived).Funktion(); Aufgabe 17: versteckte Wiederentdecken Ergänze die Anzeigefunktion der abgeleiteten Klasse so, dass die Anzeigefunktion der Basisklasse aufgerufen wird. Rufe im Hauptprogramm die Anzeigefunktion der Basisklasse auf einer Variablen der abgeleiteten Klasse auf. Static vs. Dynamic Binding beim Linken werden alle Namen (Variable und Funktionen) durch Adressen ersetzt beim Übersetzen ist nicht immer bekannt, welche Funktion aufgerufen werden soll Static vs. Dynamic Binding class base { public void Show(); } class A : public base { public void Show(); } void Display(base &object) { object.Show(); } A myA; Display(myA); class B : public base { public void Show(); } Static vs. Dynamic Binding: Virtuell Schlüsselwort virtual zur Kennzeichnung dynamischer Bindungen public virtual void Show(); Objekte besitzen zur Laufzeit einen virtual table mit den aktuellen Adressen virtueller Funktionen Adressen werden beim Konstruktoraufruf in die Tabelle eingefügt jede Methode, die eine virtuelle Methode überschreibt ist ebenfalls virtuell Abstrakte Methoden ähnlich virtuellen Methoden, jedoch wird in der Basisklasse keine Implementierung vorgenommen abgeleitete Klassen müssen die abstrakte Methode der Basisklasse implementieren von Klassen mit abstrakten Methoden kann keine Instanz erstellt werden public virtual void Show() = 0; Aufgabe 18: Virtuell abstrakt Erstelle eine Klasse 'base', die eine Methode 'show' besitzt, welche anzeigt, dass sie aufgerufen wurde Erstelle zwei Klassen 'A' und 'B', welche von 'Base' abgeleitet wurden und die gleiche Funktionalität wie 'Base' besitzen Erstelle eine Funktion 'Display', die als Parameter die Referenz auf eine Variable vom Typ 'Base' erwartet und auf diese die Methode 'show' aufruft. Stelle sicher, dass die Methode 'show' der aufrufenden Variable benutzt wird. Erstelle je eine Instanz der erstellten Klassen und übergib diese an die Funktion 'Display' mache aus der virtuellen Methode 'show' der Klasse 'Base' eine abstrakte Methode Klassen und Pointer dynamisches Erzeugen der Objekte Klasse1 *VarName = new Klasse2; Klasse2 muss entweder (auch über mehrere Ebenen) von Klasse 1 abgeleitet sein oder gleich Klasse 1 jede Klasse muss einen virtuellen Destruktor besitzen, da sonst immer der Destruktor von Klasse1 aufgerufen wird. Aufgabe 19: Klassen und Pointer Verwende die in Aufgabe 18 erstellten Klassen 'Base', 'A' und 'B' nun mit Pointern Ändere die Funktion 'Display' so ab, dass sie einen Pointer auf die Klasse 'Base' entgegennimmt Erstelle einen Vektor, der 3 Elemente der Klasse 'Base' aufnehmen kann Fülle den Vektor mit je einem Objekt der oben aufgeführten Klassen Rufe für jedes Element des Vektors die Funktion 'Display' auf Templates – Function Templates Funktionen mit dynamischen Parametertypen Typ des Parameters wird mit einem generischen Namen ersetzt Tatsächlich verwendeter Typ von Aufrufparametern abhängig template <class X, class Y ...> FunctionName(X var1, Y var2, ...) { ... } Templates – Function Templates konkrete Festlegung des tatsächlichen Datentyps beim Funktionsaufruf alle mit dem generischen Datentyp durchgeführten Operationen müssen mit dem tatsächlichen Datentyp durchführbar sein Aufruf eines Function Templates unterscheidet sich nicht vom Aufruf einer normalen Funktion Function Templates – hinter den Kulissen Compiler identifiziert beim Funktionsaufruf die generischen Teile Aufrufparameter werden mit den generischen Teilen verglichen Ersetzen des generischen durch den tatsächlichen Typ im Funktionsrumpf Resultierende Funktion wird vom Compiler übersetzt Aufruf der nun erstellten Funktion wird an der Aufrufstelle eingesetzt Function Templates Definition der Template-Funktion muss (vorerst) im Header geschehen Namen des generischen Parameters möglichst sprechend gestalten Rückgabewert ebenfalls als generischer Typ möglich Overloading mit konkreten Implementierungen ist möglich Aufgabe 20: Template Max erstelle eine Templatefunktion, die ein Array und dessen Länge als generische Parameter übernimmt und als Ergebnis den Index des Elementes mit dem größten Wert zurückgibt (bei mehreren, das erste Vorkommen) Teste diese Funktion, indem du sie mit einem int32-Array, einem double-Array und einem char-Array aufrufst Template Klassen äquivalent zu Template-Funktionen beim Erzeugen von Instanzen muss der Typ angegeben werden Memberfunktionen müssen in der Headerdatei deklariert werden (oder per #include direkt nach der Klassendeklaration eingebunden) TemplateClass<Typ> var; template <class theType> returnType ClassName<theType>::functName (...)