Vorlesung Datenstrukturen Objektorientierung in C++ (3) Aspekte der Vererbung (1) Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 546
Zuweisung bei Vererbung Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 547
Zuweisung bei Vererbung Zuweisung Resultat Variable der Basisklasse = Unterklasseninstanz Variable der Unterklasse = Basisklasseninstanz Referenzvariable der Basisklasse = Unterklasseninstanz Zeigervariable der Basisklasse = Zeiger auf Unterklasseninstanz Aufgrund der Wertsemantik der Zuweisung ist das kopierte Objekt vom Basisklassentyp, d.h. dass Erweiterungen der Unterklasse verloren gehen Kein Polymorphismus! Ist standardmäßig nicht möglich. Es ist nicht klar, wie der für Erweiterungen nötige Speicher alloziiert werden soll. Allerdings kann diese Variante durch Überladen des Standardzuweisungsoperators ermöglicht werden. Die Basisklassenvariable verhält sich trotz Referenz auf eine Unterklasseninstanz nur wie die Basisklasse Kein Polymorphismus! Obwohl die Zeigervariable nach der Zuweisung auf ein Objekt der Unterklasse verweist, verhält sich dieses wie ein Objekt der Basisklasse Kein Polymorphismus! Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 548
Polymorphismus in C++ Folgerung Bei Vererbung für Zuweisungsoperationen gibt es keinen impliziten Polymorphismus. Ursache C++ ist auf Effizienz getrimmt und die Klasse eines Objekts ist (bei Vererbung) während der Kompilierung nicht immer herauszufinden. Eine durchgängig dynamische Bestimmung zur Laufzeit (wie z.b. in Java) verursacht einen zusätzlichen Aufwand, der häufig nicht nötig ist. Expliziter Polymorphismus Um polymorphes Verhalten und damit eine Klassenbestimmung zur Laufzeit zu erreichen, muss eine Methode explizit mit Hilfe des Schlüsselwortes virtual gekennzeichnet werden. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 549
Virtuelle Klassen Konsequenz virtueller Methoden Klassen, die mindestens eine virtuelle Methode besitzen, werden als virtuelle Klassen bezeichnet. Virtueller Destruktor Sobald Zeiger vom Typ der Basisklasse auf Objekte einer abgeleiteten Klasse verweisen, sollte auch der Destruktor der Basisklasse virtuell sein. Sonst würde nur der Destruktor der Basisklasse ausgeführt werden und alle Erweiterungen von Unterklassen (selbst statische Attribute!) verblieben im Speicher. Bei unterschiedlicher Freispeicherverwaltung in abgeleiteten Klassen müssen natürlich individuelle Destruktoren implementiert werden. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 550
Zuweisung bei virtuellen Methoden Zuweisung Resultat Variable der Basisklasse = Unterklasseninstanz Aufgrund der Wertsemantik der Zuweisung ist das kopierte Objekt weiterhin vom Basisklassentyp, d.h. dass Erweiterungen der Unterklasse verloren gehen. Kein Polymorphismus! Referenzvariable der Basisklasse = Unterklasseninstanz Zeigervariable der Basisklasse = Zeiger auf Unterklasseninstanz Virtuelle Funktionen greifen auf die Implementierung der zur Laufzeit gültigen Klasse zu und weisen damit polymorphes Verhalten auf. Nichtvirtuelle Methoden benutzen weiterhin die Implementierung der Basisklasse. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 551
Abstrakte Klassen Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 552
Motivation anhand eines Beispiels Aufgabe Erstellen einer Modellierungssoftware für den Architekturbereich Grundforderungen an Funktionalität Erzeugung verschiedener geometrischer Formen: zunächst Beschränkung auf Kreis, Quadrat und Rechteck, aber später einfache Ergänzung weiterer Formen wünschenswert Implementierung einer Flächenberechnung, sowohl für alle geometrischen Formen einzeln als auch eine kumulative Flächenberechnung für mehrere verschiedene erzeugte Formen. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 553
Erster Entwurf Schritte Objektidentifikation Beschreibung Erkennen von Gemeinsamkeiten Beziehungsanalyse Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 554
Erster Entwurf r (x,y) class Circle { double x, y, r; Schritte Objektidentifikation Beschreibung Erkennen von Gemeinsamkeiten b (x,y) a a b class Rectangle { double x, y, a, b; Beziehungsanalyse a a (x,y) a a class Square { double x, y, a; Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 555
Erster Entwurf r (x,y) class Circle { double x, y, r; Schritte Objektidentifikation Beschreibung Erkennen von Gemeinsamkeiten (x,y) a b class Rectangle { double x, y, a, b; Beziehungsanalyse (x,y) a class Square { double x, y, a; Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 556
Erster Entwurf r (x,y) class Circle { double x, y, r; Schritte Objektidentifikation Beschreibung Erkennen von Gemeinsamkeiten (x,y) a b class Rectangle { double x, y, a, b; Beziehungsanalyse Erkenntnisse gemeinsame Attribute und Methoden x, y, (x,y) a class Square { double x, y, a; area() Auslagern in gemeinsame Oberklasse Quadrat ist Spezialfall eines Rechtecks Square ist Unterklasse von Rectangle Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 557
Klassenhierarchie r (x,y) class Circle { double x, y, r; Shape class Rectangle { (x,y) a b double x, y, a, b; Rectangle Circle (x,y) a class Square { double x, y, a; Square Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 558
Implementierung von Shape (1) Shape class Shape { double x, y; double area() {? Rectangle Circle Hinweis Aus Gründen der Übersichtlichkeit werden im Folgenden weder Konstruktoren, Setter oder Getter noch Sichtbarkeiten dargestellt. Square In der Regel sind Datenelemente als private oder protected, Methoden und die Ableitung von Klassen dagegen als public anzusehen. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 559
Implementierung Klasse Circle Shape class Shape { double x, y; double area() {? Rectangle Square Circle class Circle : Shape { // erbt x, y und area() double r; // Radius double area() { // verfeinern return 3.14159 * r * r; Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 560
Implementierung Rectangle / Square Shape class Shape { double x, y; double area() {? Rectangle Square Circle class Rectangle : Shape { // erbt x, y und area() double a, b; double area() { // verfeinern return a * b; class Square : Rectangle { // erbt a (und b) double area() { return a * a; Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 561
Implementierung Klasse Shape (2) Shape class Shape { double x, y; double area() {? Rectangle Square Circle Frage Wie area() implementieren? Zwei Lösungsvorschläge 1. Realisierung nur in Unterklassen? 2. Nullwerte (z.b. neg. Flächen) als Ergebnis? Problem 1. Nicht Aufgabenadäquat 2. Redundant und schlechter Stil Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 562
Abstrakte Methoden Definition Abstrakte Methoden sind Methoden ohne Rumpf, d.h. dass sie nur deklariert aber nicht implementiert werden. Syntax Abstrakte Methoden werden wie normale Methoden deklariert. Zusätzlich wird das Schlüsselwort virtual vorangestellt und dem Funktionskopf der Wert 0 zugewiesen. virtual Rückgabetyp Funktionsname ( Argumentliste ) = 0 Implementierung Abstrakte Methoden werden in abgeleiteten Klassen implementiert. Dabei kann die Implementierung stufenweise entlang der Vererbungshierarchie erfolgen. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 563
Abstrakte Klassen Konsequenz abstrakter Methoden Klassen, die mindestens eine abstrakte Methode enthalten, sind selbst abstrakt. Kennzeichnung Abstrakte Klassen werden nicht explizit als abstrakt gekennzeichnet. Bedeutung Abstrakte Klassen dienen zur Gliederung und Bereitstellung von Funktionalität, die konkret erst von Unterklassen benutzt wird. class Shape { double x, y; virtual double area() = 0; Achtung Von abstrakten Klassen können keine Instanzen gebildet werden! Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 564
Verwendung der Klasse Shape Wunsch Berechnung der Gesamtfläche aller instanziierten geometrischen Formen Voraussetzung Es befinden sich N verschiedene Formen (Objekte) in einem Feld vom Typ Shape, d.h. N Zeiger vom Typ Shape verweisen auf existierende geometrische Formen. Berechnung der kumulierten Fläche double sumarea( Shape* s[], int N ) double sum = 0.0; for ( int i = 0; i < N; i++ ) sum += s[i]->area(); return sum; Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 565
Zusammenfassung abstrakte Klassen Der Einsatz abstrakter Klassen ermöglicht: gleichartige Funktionalität, die erst in Unterklassen (meist individuell) konkretisiert werden kann, schon in Oberklassen zu definieren. Durch Verwendung der (abstrakten) Funktionalität der Oberklasse müssen nutzende Applikationen (z.b. aggregierende Funktionen) den Zugriff nur einmal implementieren. Die Auswahl der tatsächlichen Implementierung erfolgt zur Laufzeit durch Polymorphismus Realisierung durch abstrakte Methoden Funktionalität, die unmodifiziert in der Oberklasse und in Unterklassen Verwendung finden kann, nur einmal in der abstrakten Oberklasse bereitzustellen Realisierung durch konkrete Methoden eine automatische Integritätssicherung, da eine Instanzerzeugung erst bei (nicht abstrakten) Unterklassen möglich ist. Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 566
Ende der Vorlesung Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 567