18. Vererbung und Polymorphie

Ähnliche Dokumente
Grundlagen Polymorphismus Eigenschaften virtueller Klassen Mehrfachvererbung bei ROOT. Mehrfache Vererbung. Daniel Beneckenstein. 21.

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

Vererbung und Polymorphie

Rückblick: Benutzerdefinierte Datentypen Definition der Klasse Vektor als Container für 2-dimensionale Vektoren

Überblick. Überblick. Abstrakte Klassen - rein virtuelle Funktionen Beispiele

C++ Teil 9. Sven Groß. 17. Juni Sven Groß (IGPM, RWTH Aachen) C++ Teil Juni / 17

Objektorientierte Programmierung mit C++ SS 2007

Algorithmen und Datenstrukturen Musterlösung 5

Algorithmen und Datenstrukturen I Bruder-Bäume

Polymorphismus 179. Function.h. #include <string>

Vorlesungsprüfung Programmiersprache 1

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

"Roman Jachs" PR Überblick C++ Roman Jachs 5 AHD 1998/99. Überblick C++

C++ Notnagel. Ziel, Inhalt. Programmieren in C++

Vererbung I. Kfz Eigenschaften und Methoden der Klasse Kfz Lkw. Pkw. Eigenschaften und Methoden der Klasse Kfz

Algorithmen und Datenstrukturen

C++ Teil 10. Sven Groß. 17. Dez IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Dez / 14

Programmierkurs C/C++

Thema heute: Vererbung und Klassenhierarchien. Abgeleitete Klassen. Vererbung von Daten und Funktionen. Virtuelle Funktionen

OOP und Angewandte Mathematik (Praktikum 1) Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

Neben der Verwendung von Klassen ist Vererbung ein wichtiges Merkmal objektorientierter

Einführung in C++ Operatoren überladen (Klassen)

1 Abstrakte Klassen, finale Klassen und Interfaces

Programmieren II Abstrakte Klassen / Virtuelle Methoden. Programmieren II Abstrakte Klassen / Virtuelle Methoden

Einführung in die Programmierung mit C++

Objektorientiertes Programmieren mit C++ für Fortgeschrittene

Übung 4: Die generische Klasse AvlBaum in Java 1

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

Thema heute: Vererbung und Klassenhierarchien. Abgeleitete Klassen. Vererbung von Daten und Funktionen. Virtuelle Funktionen

! 1. Rekursive Algorithmen.! 2. Rekursive (dynamische) Datenstrukturen. II.3.2 Rekursive Datenstrukturen - 1 -

3. Java - Sprachkonstrukte I

13. Vererbung. Prof. Dr. François E. Cellier Informatik I für D-ITET (HS 2012)

Institut für Programmierung und Reaktive Systeme. Java 2. Markus Reschke

C++ - Einführung in die Programmiersprache Polymorphismus und Vererbung. Eltern

Name: Klausur Informatik III WS 2003/04

float: Fließkommazahl nach IEEE 754 Standard mit 32 bit

4. Objektorientierte Programmierung mit C++

Dynamische Datentypen

12 Abstrakte Klassen, finale Klassen und Interfaces

Einführung in C# Teil 3. Matthias Nübling

7. Übung Informatik II - Objektorientierte Programmierung

C++ Klassen, Vererbung. Philipp Lucas. Sebastian Hack. Wintersemester 2008/09. saarland.

Programmieren in C++ Überladen von Methoden und Operatoren

Vorausgesetzte Grundkenntnisse. Inhalt. Klassenhierarchie und Vererbung. Vererbung. Klassenhierarchie und Vererbung. Einführung in C# Teil 3

Wiederholungsklausur "ADP" WS 2016/2017

Lambda-Funktionen. Lambda-Funktionen. Lambda-Funktionen sollen

Informatik II Vorlesung am D-BAUG der ETH Zürich

C++-Zusammenfassung. H. Schaudt. August 18, 2005

Alltagsnotizen eines Softwareentwicklers

Einführung in C++ Vererbung und Polymorphismus

5. Behälter und Iteratoren. Programmieren in C++ Überblick. 5.1 Einleitung. Programmieren in C++ Überblick: 5. Behälter und Iteratoren

Algorithmen zur Datenanalyse in C++

Themen. Statische Methoden inline Methoden const Methoden this Zeiger Destruktor Kopierkonstruktor Überladen von Operatoren

Binärbäume. Prof. Dr. E. Ehses,

Abgabe: (vor 12 Uhr)

Vererbung. Martin Wirsing. Ziele. Vererbung

Exceptions und Vererbung

Grundlagen der Informatik

Grundlagen der Informatik 12. Strukturen

Programmieren 2 C++ Überblick

Die abgeleiteten Klassen Kreis und Viereck erben die Elemente des Basisklasse und verfügen über zusätzliche Eigenschaften (Seitenlänge,

Vererbung und Polymorphie

11 Vererbung und Klassenhierarchie

Praxisorientierte Einführung in C++ Lektion: "Vererbung"

Lösung der OOP-Prüfung WS12/13

14 Abstrakte Klassen, finale Klassen, Interfaces

Software Entwicklung 1

12. Vererbung. Prof. Dr. Markus Gross Informatik I für D-ITET (WS 03/04)

14 Abstrakte Klassen, finale Klassen, Interfaces. Auswertung von Ausdrücken. Beispiel. Abstrakte Methoden und Klassen

Objektorientierung (OO)

Informatik II Übung 06. Benjamin Hepp 5 April 2017

HSR Rapperswil 2001 Markus Rigling. Programmieren: Vererbung. 1 Variante 2

Transkript:

590 18. Vererbung und Polymorphie Ausdrucksbäume, Vererbung, Code-Wiederverwendung, virtuelle Funktionen, Polymorphie, Konzepte des objektorientierten Programmierens

(Ausdrucks-)Bäume 591 -(3-(4-5))*(3+4*5)/6 Astgabel / Wurzel Astgabel 6 Knick 3 4 5 + 3 4 5 Blatt

592 Astgabeln + Blätter + Knicke = Knoten Knoten / 6 Knoten Wert Operator Linker Operand Rechter Operand tree_node / * = 6 : nicht benutzt

Knoten (struct tree node) tree_node op val left right struct tree_node { char op; // internal node ( op: +,,, / ) tree_node left; tree_node right; // leaf node (op: = ) double val; // constructor tree_node (char o, tree_node l, tree_node r, double v) : op (o), left (l ), right (r ), val (v) { ; 593

Knoten und Teilbäume 594 / 6 + 3 Knoten = Wurzel eines Teilbaums 3 4 5 4 5

Knoten in Teilbäumen zählen 595 struct tree_node { op val left right // POST: returns the size (number of nodes) of // the subtree with root this int size () const { int s=1; if (left) s += left >size(); if (right) s += right >size(); return s; ;

596 Teilbäume auswerten struct tree_node { op val left right // POST: evaluates the subtree with root this double eval () const { if (op == = ) return val; Blatt... double l = 0;... oder Astgabel: if (left) l = left >eval(); op unär, oder linker Ast double r = right >eval(); rechter Ast if (op == + ) return l + r; if (op == ) return l r; if (op == ) return l r; if (op == / ) return l / r; assert (false); // unknown operator return 0; ;

Teilbäume klonen 597 struct tree_node { op val left right // POST: a copy of the subtree with root this is // made, and a pointer to its root node is // returned tree_node copy () const { tree_node to = new tree_node (op, 0, 0, val); if (left) to >left = left >copy(); if (right) to >right = right >copy(); return to; ;

598 Teilbäume fällen struct tree_node { op val left right // POST: all nodes in the subtree with root // this are deleted, except this itself void clear() { if (left) { left >clear(); delete left; + if (right) { 3 right >clear(); delete right; 3 ; 4 5 4 5

599 Bäumige Teilbäume struct tree_node { // constructor tree_node (char o, tree_node l, tree_node r, double v) // functionality double eval () const; void print (std::ostream& o) const; int size () const; tree_node copy () const; void clear (); ;

Bäume pflanzen 600 class texpression { private: tree_node root; public: texpression (double d) ; erzeugt Baum mit einem Blatt : root (new tree_node ( =, 0, 0, d)) {

Bäume wachsen lassen texpression& operator = (const texpression& e) { assert (e.root); root = new tree_node (, root, e.root >copy(),0); return this; root root *this e.root->copy() e.root *this e e 601

Bäume züchten 602 texpression operator (const texpression& l, const texpression& r) { texpression result = l; return result = r; texpression a = 3; texpression b = 4; texpression c = 5; texpression d = a b c; 3 4 5

Bäume züchten 603 Es gibt für texpression auch noch Default-Konstruktor, Copy-Konstruktor, Assignment-Operator, Destruktor die arithemtischen Zuweisungen +=, *=, /= die binären Operatoren +, *, / das unäre-

Werte zu Bäumen! typedef texpression value; 604 // term = factor factor " " term factor "/" term. value term (value v, char sign, std :: istream& is){ if (sign == ) v = factor(is ); else if (sign == / ) v /= factor(is ); else v = factor( is ); char c = lookahead (is); if (c == c == / ) return term (v, c, is >> c ); return v; calculator_l.cpp (Ausdruckswert) exp_calculator_l.cpp (Ausdrucksbaum)

Motivation Vererbung: Bisher Knoten / Knoten 6 Knoten 3 + 3 4 5 4 5 Knoten = 5 Astgabeln + Blätter + Knicke = Knoten Unbenutzte Membervariablen 605

Motivation Vererbung: Die Idee left right Binäre Division / Binäre Multiplikation 6 Betrag right abs 3 + 3 4 5 4 5 Zahl val Überall nur die benötigten Membervariablen! Zoo-Erweiterung mit neuen Knoten! 606

Vererbung Der Hack, zum ersten... 607 Szenario: Erweiterung des Ausdrucksbaumes um mathematische Funktionen, z.b. abs, sin, cos: Erweiterung der Klasse tree_node um noch mehr Membervariablen struct tree_node{ char op; // neu: op = f > Funktion std::string name; // function name; Nachteile: Veränderung des Originalcodes (unerwünscht) Noch mehr unbenutzte Membervariablen...

Vererbung Der Hack, zum zweiten... 608 Szenario: Erweiterung des Ausdrucksbaumes um mathematische Funktionen, z.b. abs, sin, cos: Anpassung jeder einzelnen Memberfunktion double eval () const { else if (op == f ) if (name == "abs") return std::abs(right >eval()); Nachteile: Verlust der Übersichtlichkeit Zusammenarbeit mehrerer Entwickler schwierig

Vererbung die saubere Lösung Aufspaltung von tree_node xtree node number node unary node binary node minus node abs node Gemeinsame Eigenschaften verbleiben in der Basisklasse xtree_node (Erklärung folgt) 609

Vererbung 610 Klassen können Eigenschaften (ver)erben: struct xtree_node{ virtual int size() const; virtual double eval () const; ; erbt von Vererbung sichtbar struct number_node : public xtree_node { double val; nur für number_node int size () const; double eval () const; ; Mitglieder von xtree_node werden überschrieben

Vererbung Nomenklatur 611 class A { Basisklasse (Superklasse) class B: public A{ class C: public B{ Abgeleitete Klasse (Subklasse) B und C erben von A C erbt von B

612 Aufgabenteilung: Der Zahlknoten struct number_node: public xtree_node{ double val; number_node (double v) : val (v) { double eval () const { return val; int size () const { return 1; ;

Ein Zahlknoten ist ein Baumknoten... 613 Ein (Zeiger auf ein) abgeleitetes Objekt kann überall dort verwendet werden, wo ein (Zeiger auf ein) Basisobjekt gefordert ist, aber nicht umgekehrt. number_node num = new number_node (5); xtree_node tn = num; // ok, number_node is // just a special xtree_node xtree_node bn = new add_node (tn, num); // ok number_node nn = tn; //error:invalid conversion

614 Anwendung class xexpression { private : xtree_node root; statischer Typ public: dynamischer Typ xexpression (double d) : root (new number_node (d)) { xexpression& operator = (const xexpression& t) { assert (t.root); root = new sub_node (root, t.root >copy()); return this ;

Polymorphie Virtuelle Mitgliedsfunktion: der dynamische Typ bestimmt bei Zeigern auf abgeleitete Objekte die auszuführenden Memberfunktionen struct xtree_node { virtual double eval(); ; Ohne virtual wird der statische Typ zur Bestimmung der auszuführenden Funktion herangezogen. Wir vertiefen das nicht weiter. 615

616 Aufgabenteilung: Binäre Knoten struct binary_node : public xtree_node { xtree_node left; // INV!= 0 xtree_node right; // INV!= 0 binary_node (xtree_node l, xtree_node r) : left (l), right (r) size funktioniert für { alle binären Knoten. assert (left); Abgeleiteten Klassen assert (right); (add_node,sub_node... ) erben diese Funktion! int size () const { return 1 + left >size() + right >size(); ;

Aufgabenteilung: +, -, * 617 struct sub_node : public binary_node { sub_node (xtree_node l, xtree_node r) : binary_node (l, r) { double eval () const { return left >eval() right >eval(); ; eval spezifisch für +, -, *, /

Erweiterung um abs Funktion 618 xtree node unary node number node binary node abs node minus node add node sub node mul node div node

619 Erweiterung um abs Funktion struct unary_node: public xtree_node { xtree_node right; // INV!= 0 unary_node (xtree_node r); int size () const; ; struct abs_node: public unary_node { abs_node (xtree_node arg) : unary_node (arg) { ; double eval () const { return std::abs (right >eval());

Da ist noch was... Speicherbehandlung 620 struct xtree_node { // POST: a copy of the subtree with root // this is made, and a pointer to // its root node is returned virtual xtree_node copy () const; // POST: all nodes in the subtree with // root this are deleted, except // this itself virtual void clear () {; ;

Da ist noch was... Speicherbehandlung 621 struct unary_node: public xtree_node { virtual void clear () { right >clear(); delete right; ; struct minus_node: public unary_node { xtree_node copy () const { return new minus_node (right >copy()); ;

622 Kein Destruktor im xtree node? Designentscheidung: Schlanke Knoten (xtree_node und abgeleitete Klassen) Speicherverwaltung in der Container-Klasse class xexpression { // Copy Konstruktor xtree_node::copy xexpression (const xexpression& v); // Zuweisungsoperator xexpression& operator=(const xexpression& v); // Destruktor ~xexpression (); ; xtree_node::clear

Mission: Monolithisch modular struct tree_node { char op; tree_node left; tree_node right; double val; ; double eval () const { if (op == = ) return val; else { double l = 0; if (left!= 0) l = left >eval(); double r = right >eval(); if (op == + ) return l + r; if (op == ) return l r; if (op == ) return l r; if (op == / ) return l / r; assert (false); // unknown operator return 0; int size () const { void clear() { tree_node copy () const { + struct number_node: public xtree_node { double val; double eval () const { return val; ; struct unary_node: public xtree_node { ; struct minus_node: public unary_node { double eval () const { return right >eval(); ; struct binary_node: public xtree_node { ; struct minus_node : public binary_node { double eval () const { return left >eval() right >eval(); struct abs_node : public unary_node { double eval () const { return left >eval() right >eval(); 623