C++ Programmierkurs. 6. Vererbung und Polymorphismus. Wintersemester 04 / 05. Christian Hagemeier Lehrstuhl Prof. Dr. Schrader

Ähnliche Dokumente
Prof. Dr. Markus Gross Informatik I für D-ITET (WS 03/04)

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

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

C++ Programmierkurs. Wintersemester 04 / 05. Christian Hagemeier. Lehrstuhl Prof. Dr. Schrader Institut für Informatik Universität zu Köln

Vorlesung Datenstrukturen

11.3 Virtuelle Methoden

Übung zur Vorlesung Wissenschaftliches Rechnen Sommersemester 2012 Auffrischung zur Programmierung in C++, 2. Teil

Einführung in die Programmierung mit C++

Polymorphismus 44. Function.hpp. #include <string>

Mapra: C++ Teil 6. Felix Gruber, Sven Groß. IGPM, RWTH Aachen. 13. Juni 2017

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

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

Objekt-Orientierte Programmierung: Vererbung Pearson Education, Inc. All rights reserved.

Grundkurs C++ IDE Klassenhierarchien

11.3 Virtuelle Methoden

Objektorientierte Programmierung mit C++ SS 2007

Grundkurs C++ IDE Klassenhierarchien

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

Informatik - Übungsstunde

Grundkurs C++ IDE Klassenhierarchien

Implementieren von Klassen

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

C++ Programmierkurs. 5. Klassen. Wintersemester 04 / 05. Christian Hagemeier Lehrstuhl Prof. Dr. Schrader

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

Vererbung und Polymorphie

Programmierpraktikum 3D Computer Grafik

C++ - Objektorientierte Programmierung Polymorphie

Prinzipien der objektorientierten Programmierung (OOP)

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

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

Einstieg in die Informatik mit Java

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

7. Übung Informatik II - Objektorientierte Programmierung

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

Programmieren in Java

Algorithmen und Datenstrukturen

Vererbung und Polymorphie

Übersicht. Bisherige Verwendung von Klassen Vererbung. Zeiger auf Objekte (abgeleiteter) Klassen Virtuelle Funktionen Konstruktoren/Destruktoren

C++ Teil 12. Sven Groß. 18. Jan Sven Groß (IGPM, RWTH Aachen) C++ Teil Jan / 11

Programmierkurs. Steffen Müthing. January 18, Interdisciplinary Center for Scientific Computing, Heidelberg University

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

Praxisorientierte Einführung in C++ Lektion: "Virtuelle Methoden"

Vererbung, Polymorphie

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

Einführung in die Programmierung mit C++

Einführung in die Programmierung Wintersemester 2008/09

Informatik 1 ( ) D-MAVT F2011. Klassen, Funktionen. Yves Brise Übungsstunde 9

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

Grundlagen der Informatik

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

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

Informatik I (D-ITET)

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

C++ Klassen weitere Funktionen

Einführung in das Objektorientierte Programmieren mit C++

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

10.4 Konstante Objekte

Vererbung. Gerd Bohlender. Institut für Angewandte und Numerische Mathematik. Vorlesung: Einstieg in die Informatik mit Java 23.5.

Programmieren in Java

Crashkurs C++ Wiederholung

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

Objektorientierte Programmierung III

3D Programmierpraktikum: Einführung in C++ - Teil 2

Einstieg in die Informatik mit Java

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

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

Allgemeines - Prinzipien

Programmierung und Angewandte Mathematik

Mikrorechentechnik II. Klassen in C++

Objektorientierung (OO)

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

Einführung in C++ Vererbung und Polymorphismus

Kapitel 13. Definition von Klassen. OOP Thomas Klinker 1

Programmierkurs C/C++

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

Angewandte Mathematik in OOP WS 2011/12. Abschluss-Test

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

Programmierkurs C/C++

Musterübung 09: Vererbung und Dynamische Bindung

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Wiederholung: Gerüstbeispiel. Vererbungshierarchie: Typ 0

Objektorientierte Programmierung mite**

Exceptions und Vererbung

Objektorientierte Programmierung mit C++

Objektorientierte Programmierung

Bereits behandelt: Klassen, Konstruktoren, Destruktoren etc. Operatoren. Heute: Namensräume. Vererbung. Kompaktkurs C++ Themen F 1

Probeklausur. Musterlösung

Vererbung Was versteht man unter dem Begriff Vererbung?

Die verschiedenen Programmierparadigmen von C++ Software-Technik: Vom Programmierer zur erfolgreichen

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

Kapitel 8 Vererbung. Korbinian Molitorisz. IPD Tichy Lehrstuhl für Programmiersysteme

Vererbung. Was versteht man unter dem Begriff Vererbung?

Informatik I (D-MAVT)

Informatik II Übung, Woche 17

Einführung in die Programmierung Wintersemester 2016/17

Einführung in die Programmiersprache Java II

Einstieg in die Informatik mit Java

Transkript:

C++ Programmierkurs 1 6. Vererbung und Polymorphismus 3 Wintersemester 04 / 05 Christian Hagemeier Lehrstuhl Prof. Dr. Schrader Institut für Informatik Universität zu Köln 6.1 Einführung in Vererbung 6.2 Vererbung in C++ 6.3 Grundlagen des Polymorphismus 6.4 Abstrakte Klassen 6.5 Virtuelle Destruktoren mittwochs 17 18:30 Uhr Hörsaal II der Physikalischen Institute http://www.zaik.de/afs/teachings/ 2 4 Gliederung der Vorlesung 6.1 Einführung in Vererbung 20.10.: Organisatorisches und Einführung 27.10.: Einführung und Kontrollstrukturen 03.11.: Kontrollstrukturen 10.11.: Kontrollstrukturen und Funktionen 17.11.: Funktionen 24.11.: Vektoren, Zeiger 01.12.: Zeiger, Strings 08.12.: Klassen (1) 15.12.: Klassen (2), Überladen von Operatoren 22.12.: Vererbung und Polymorphismus 12.01.: Datei und Stream Ein /Ausgabe, Diverses Wiederverwendbarkeit Erzeugen einer Klasse aus existierender Basisklasse "erbt" Daten und Verhalten der Basisklasse "Verfeinerung" mit weiteren Details stärker spezialisierte Gruppe an Objekten wird abgebildet Verhalten der Ursprungsklasse kann modifiziert werden Vererbung über mehrere Stufen möglich (indirekte Vererbung) Mehrfachvererbung möglich (Vererbung von mehreren Basisklassen)

Beziehungen im Objektmodell 5 Vererbungshierarchie: Beispiel 1 7 Abstraktion zielt auf Gemeinsamkeiten der Klassen im Modell "ist ein"-beziehung wird im Objektmodell durch Vererbung abgebildet Objekte der abgeleiteten Klasse können als Objekte der Basisklasse betrachtet werden Beispiel Husky ist ein Hund: Huskies besitzen alle Eigenschaften eines Hundes "hat ein"-beziehung Komposition: Klassenattribut von diesem Typ Objekt enthält ein oder mehrere Objekte anderer Klassen als Variablen Beispiel Hund hat einen Kopf Administrator Faculty Employee Teacher AdministratorTeacher CommunityMember Staff Student Single inheritance Multiple inheritance Alumnus Single inheritance Single inheritance Basisklasse und abgeleitete Klasse 6 Vererbungshierarchie: Beispiel 2 8 Basisklasse spiegelt typischerweise größere Objektmenge wieder als abgeleitete Klasse Beispiele: Shape Basisklasse Student Shape Loan Employee Account abgeleitete Klassen GraduateStudent UndergraduateStudent Circle Triangle Rectangle CarLoan HomeImprovementLoan MortgageLoan FacultyMember StaffMember CheckingAccount SavingsAccount TwoDimensionalShape ThreeDimensionalShape Circle Square Triangle Sphere Cube Tetrahedron

6.2 Vererbung in C++ 9 Zugriffssteuerung protected 11 3 Arten der Vererbung: public Jedes Objekt der abgeleiteten Klasse ist auch Objekt der Basisklasse Objekte der Basisklasse sind keine Objekte der abgeleiteten Kl. Beispiel: Alle Huskies sind Hunde, nicht alle Hunde sind Huskies Nichtprivate Elemente der Basisklasse können verwendet werden (durch vererbte nicht-private Methoden) private Alternative zu Komposition (siehe "hat ein"-beziehung) protected selten genutzt Zwischenstufe zwischen public und private Zugriff auf protected Klassenmitglieder wie bei private und protected: durch Basisklassenmethoden durch friend-funktionen der Basisklasse Schärfer als public, laxer als private: durch Methoden der abgeleiteten Klasse durch friend-funktionen der abgeleiteten Klasse Zugriff nicht möglich von externen Klassen Nutzung der public- und protected-methoden von Basisklassen: einfach Methodenname verwenden! public-vererbung 10 Aufteilung des Quellcodes auf Dateien (1) 12 Syntax: class TwoDimensionalShape : public Shape Klasse TwoDimensionalShape erbt von Klasse Shape private Elemente der Basisklasse: sind nicht direkt verfügbar werden trotzdem mit vererbt (Zugriff über entsprechende Methoden) public- und protected-methoden und -Variablen werden so "übernommen" friend-funktionen werden nicht vererbt Headerdateien Deklarationen von globalen Variablen Prototypen von Funktionen Deklaration von Klassen mit Methodenprototypen Implementationsdateien Implementation der Funktionen und Klassen Insgesamt eine main()-funktion in allen Implementationsdateien Problem: Sicherstellen, daß jede Deklaration nur einmal vorgenommen wird Lösung: Präprozessoranweisungen #ifndef <marke>: wenn <marke> nicht definiert ist, binde folgenden Code ein, sonst überspringe ihn #define <marke>: definiert <marke> #endif: Gegenstück zu vorangegangenen #ifndef

13 15 Aufteilung des Quellcodes auf Dateien (2) Genereller Aufbau: #ifndef _test_h_ #define _test_h_ // hier kommt der Quellcode mit den // Deklarationen hin #endif Einbinden der Deklaration vor Nutzung/Definition mittels #include "dateiname" Vorgehen beim Kompilieren Jede Implementationsdatei wird vom Compiler separat in Objektcode übersetzt Diese Objektcode-Dateien werden vom Linker zum ausführbaren Programm zusammengebunden Beispiel "Punkt": Implementationsdatei (1) 1 // Fig. 9.13: point2.cpp 2 // Point2 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "point2.h" // Point2 class definition 8 9 // default constructor 10 Point2::Point2( int xvalue, int yvalue ) 11 { 12 x = xvalue; 13 y = yvalue; 14 15 } // end Point2 constructor 16 17 // set x in coordinate pair 18 void Point2::setX( int xvalue ) 19 { 20 x = xvalue; // no need for validation 21 22 } // end function setx 14 16 Beispiel "Punkt": (Headerdatei) Beispiel "Punkt": Implementationsdatei (2) 1 // Fig. 9.12: point2.h 2 // Point2 class definition represents an x-y coordinate pair. 3 #ifndef POINT2_H 4 #define POINT2_H 5 6 class Point2 { 8 public: 9 Point2( int = 0, int = 0 ); // default constructor 10 11 void setx( int ); // set x in coordinate pair 12 int getx() const; // return x from coordinate pair 13 14 void sety( int ); // set y in coordinate pair 15 int gety() const; // return y from coordinate pair 16 17 void print() const; // output Point2 object 18 19 protected: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 23 // end class Point2 }; 24 25 #endif 24 // return x from coordinate pair 25 int Point2::getX() const 26 { 27 return x; 28 29 } // end function getx 30 31 // set y in coordinate pair 32 void Point2::setY( int yvalue ) 33 { 34 y = yvalue; // no need for validation 35 36 } // end function sety 37 38 // return y from coordinate pair 39 int Point2::getY() const 40 { 41 return y; 42 43 } // end function gety

17 19 Beispiel "Punkt": Implementationsdatei (3) Beispiel "Kreis": Implementationsdatei (1) 45 // output Point2 object 46 void Point2::print() const 47 { 48 cout << '[' << x << ", " << y << ']'; 49 50 } // end function print 1 // Fig. 9.15: circle3.cpp 2 // Circle3 class member-function definitions. 3 #include <iostream> 4 5 using std::cout; 6 7 #include "circle3.h" // Circle3 class definition 8 9 // default constructor 10 Circle3::Circle3( int xvalue, int yvalue, double radiusvalue ) 11 { 12 x = xvalue; 13 y = yvalue; 14 setradius( radiusvalue ); 15 16 } // end Circle3 constructor 17 18 // set radius 19 void Circle3::setRadius( double radiusvalue ) 20 { 21 radius = ( radiusvalue < 0.0? 0.0 : radiusvalue ); 22 23 } // end function setradius 18 20 Beispiel "Kreis": Headerdatei Beispiel "Kreis": Implementationsdatei (2) 1 // Fig. 9.14: circle3.h 2 // Circle3 class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE3_H 4 #define CIRCLE3_H 5 6 #include "point2.h" // Point2 class definition 7 8 class Circle3 : public Point2 { 10 public: 12 // default constructor 13 Circle3( int = 0, int = 0, double = 0.0 ); 14 15 void setradius( double ); // set radius 16 double getradius() const; // return radius 17 18 double getdiameter() const; // return diameter 19 double getcircumference() const; // return circumference 20 double getarea() const; // return area 21 22 void print() const; // output Circle3 object 24 private: 25 double radius; // Circle3's radius 27 // end class Circle3 }; 29 #endif 25 // return radius 26 double Circle3::getRadius() const 27 { 28 return radius; 29 30 } // end function getradius 31 32 // calculate and return diameter 33 double Circle3::getDiameter() const 34 { 35 return 2 * radius; 36 37 } // end function getdiameter 38 39 // calculate and return circumference 40 double Circle3::getCircumference() const 41 { 42 return 3.14159 * getdiameter(); 43 44 } // end function getcircumference

Beispiel "Kreis": Implementationsdatei (3) 21 Beispiel: main()-funktion (2) 23 46 // calculate and return area 47 double Circle3::getArea() const 48 { 49 return 3.14159 * radius * radius; 50 51 } // end function getarea 52 53 // output Circle3 object 54 void Circle3::print() const 55 { 56 cout << "Center = [" << x << ", " << y << ']' 57 << "; Radius = " << radius; 58 59 } // end function print 24 circle.setx( 2 ); // set new x-coordinate 25 circle.sety( 2 ); // set new y-coordinate 26 circle.setradius( 4.25 // set new radius ); 27 28 // display new point value 29 cout << "\n\nthe new location and radius of circle are\n"; 30 circle.print(); 31 32 // display floating-point values with 2 digits of precision 33 cout << fixed << setprecision( 2 ); 34 35 // display Circle3's diameter 36 cout << "\ndiameter is " << circle.getdiameter(); 37 38 // display Circle3's circumference 39 cout << "\ncircumference is " << circle.getcircumference(); 40 41 // display Circle3's area 42 cout << "\narea is " << circle.getarea(); 43 44 cout << endl; 45 46 return 0; // indicates successful termination 48 // end main } Beispiel: main()-funktion (1) 22 Ausgabe des Beispiels 24 1 // Fig. 9.16: circletest3.cpp 2 // Testing class Circle3. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::fixed; 8 9 #include <iomanip> 10 11 using std::setprecision; 12 13 #include "circle3.h" // Circle3 class definition 14 15 int main() 16 { 17 Circle3 circle( 37, 43, 2.5 ); // instantiate Circle3 object 18 19 // display point coordinates 20 cout << "X coordinate is " << circle.getx() 21 << "\ny coordinate is " << circle.gety() 22 << "\nradius is " << circle.getradius(); X coordinate is 37 Y coordinate is 43 Radius is 2.5 The new location and radius of circle are Center = [2, 2]; Radius = 4.25 Diameter is 8.50 Circumference is 26.70 Area is 56.74

Verwendung von protected Vorteile: abgeleitete Klassen können Werte direkt modifizieren etwas schneller (Vermeidung der Verwendung von get-/set- Funktionen) Nachteile: Zulässigkeitstest innerhalb der Basisklasse wird umgangen abgeleitete Klasse kann illegale Werte zuweisen Implementationsabhängigkeit Methoden der abgeleiteten Klasse sind meist abhängiger von der Implementation der Basisklasse Modifikation der Basisklasse kann konsequenzen auf abgeleitete Klasse haben (fragile Software) 25 6.3 Grundlagen des Polymorphismus Polymorphismus: Auswahl der auszuführenden Aktion wird dynamisch durch Klasse bestimmt Kernkonzept: Abgeleitete Klassen können als Instanzen der Basisklasse behandelt werden Dadurch: Nahtloses Einfügen neuer Funktionalität/ Klassen in existierendes Modell möglich Neue Klasse können problemlos hinzugefügt werden und werden automatisch wie bisherige Klassen berücksichtigt Aufruf einer Methode, die in abgeleiteter Klasse überladen wurde: Bisher: Auswahl der ausgeführten Funktion anhand des Typs Jetzt: Auswahl der Funktion dynamisch anhand der Instanz 27 Konstruktoren, Destruktoren, Zuweisung Instantiierung der Objekte mittels geschachtelter Konstruktorenaufrufe (Basiskonstruktor nach abgeleitetem Konstruktor) Aufruf der Destruktoren in umgekehrter Reihenfolge Konstruktoren, Destruktor und Zuweisungsoperator werden nicht vererbt Aber: Konstruktoren und Zuweisungsoperator der abgeleiteten Klasse können die der Basisklasse aufrufen 26 Methodenzugriff über Zeiger Wiederholung: Zeiger müssen im Allgemeinen genau von dem Typ sein, auf dessen Objekt sie zeigen Sonst: Syntaxfehler Daher bisher möglich: Basisklassenzeiger auf Basisklasseninstanz Zeiger der abgeleiteten Klasse auf entsprechende Instanz Jetzt neu: Basisklassenzeiger auf Instanz der abgeleiteten Klasse Objekt wird als ein Objekt der Basisklasse interpretiert! Es werden auf die Daten des abgeleiteten Objekts die Methoden der Basisklasse angewendet Methodenaufruf hängt von Zeigertyp und nicht von Objekttyp ab! 28

Beispiel: Zeigerzugriff auf abgeleitete Klasse class Point { //... }; class Circle : public Point { //... }; Point p; Circle c; Point* pptr = &p; Circle* cptr = &c; pptr->print(); // print() von Point auf Point-Instanz cptr->print(); // print() von Circle auf Circle-Instanz pptr = &c; // kein Syntaxfehler, da Circle von Point // abgeleitet! pptr->print(); // print() von Point auf Circle-Instanz Circle-Instanz wird als Point interpretiert! Auswahl der Methode findet entsprechend anhand des Variablentyps (hier: Zeigertyps) statt Resultiert aus "Ist ein"-beziehung zwischen Klassen 29 Virtuelle Methoden Bisher: Zeigertyp bestimmt Methodenaufruf Neu: virtual-methoden Instanz (und NICHT Zeigertyp) bestimmt aufgerufene Methode! Wozu ist das nötig? Betrachte Klassen Circle, Triangle, Rectangle, alle von Shape abgeleitet jede besitzt eigene Methode draw() um beliebige Form zu zeichnen: Zeiger der Basisklasse Shape ruft der Reihe nach alle draw- Methoden auf Programm ermittelt richtige Zeichenfunktion zur Laufzeit (dynamisch) So können alle Formen gleich behandelt werden 31 Zeigerzugriff mit Basisklassenzeiger Es können alle Funktionen der Basisklasse auf dieser Instanz verwendet werden Aufruf genau wie bei Basisklassen-Instanzen Diese arbeiten auf den Daten der Instanz der abgeleiteten Klasse Methoden oder Variablen der abgeleiteten Klasse können nicht verwendet werden! Zugriff darauf liefert Syntaxfehler, da sie nicht in Basisklasse definiert sind Bis hier hin: Alles aus Vererbung bekannt! 30 Virtuelle Methoden in C++ Zur Verwendung virtueller Methoden in C++ muß Schlüsselwort virtual bei Methode draw angegeben werden draw muß in jeder abgeleiteten Klasse überladen werden (Methode muß gleiche Signatur besitzten!) Beispiel: virtual void draw() const; virtuelle Methoden bleiben in allen abgeleiteten Klassen virtuell Trotzdem sollte man es wegen der Klarheit in jeder Klasse dazuschreiben Dynamische Bindung: wähle korrekte Methode zur Laufzeit findet ausnahmslos mit Zeigern statt! 32

Beispiel "Kreis" mit virtueller Funktion (1) 33 Beispiel "Kreis": Testprogramm (1) 35 1 // Fig. 10.8: point.h 2 // Point class definition represents an x-y coordinate pair. 3 #ifndef POINT_H 4 #define POINT_H 5 6 class Point { 8 public: 9 Point( int = 0, int = 0 ); // default constructor 10 11 void setx( int ); // set x in coordinate pair 12 int getx() const; // return x from coordinate pair 13 Print als virtual deklariert. 14 void sety( int ); // set y in coordinate pair Wird in alle abgeleiteten 15 int gety() const; // return y from coordinate pair 16 Klassen virtual sein. 17 virtual void print() const; // output Point object 18 19 private: 20 int x; // x part of coordinate pair 21 int y; // y part of coordinate pair 23 }; // end class Point 24 25 #endif 1 // Fig. 10.10: fig10_10.cpp 2 // Introducing polymorphism, virtual functions and dynamic 3 // binding. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 using std::fixed; 9 10 #include <iomanip> 11 12 using std::setprecision; 13 14 #include "point.h" // Point class definition 15 #include "circle.h" // Circle class definition 16 17 int main() 18 { 19 Point point( 30, 50 ); 20 Point *pointptr = 0; 21 22 Circle circle( 120, 89, 2.7 ); 23 Circle *circleptr = 0; Beispiel "Kreis": Headerdatei (2) 34 Beispiel "Kreis": Testprogramm (2) 36 1 // Fig. 10.9: circle.h 2 // Circle class contains x-y coordinate pair and radius. 3 #ifndef CIRCLE_H 4 #define CIRCLE_H 6 #include "point.h" // Point class definition 7 8 class Circle : public Point { 10 public: 11 12 // default constructor 13 Circle( int = 0, int = 0, double = 0.0 ); 14 15 void setradius( double ); // set radius 16 double getradius() const; // return radius 17 18 double getdiameter() const; // return diameter 19 double getcircumference() const; // return circumference 20 double getarea() const; // return area 21 22 virtual void print() const; // output Circle object 24 private: 25 double radius; // Circle's radius 27 // end class Circle }; 29 #endif 25 // set floating-point numeric formatting 26 cout << fixed << setprecision( 2 ); 27 28 // output objects point and circle using static binding 29 cout << "Invoking print function on point and circle " 30 << "\nobjects with static binding " 31 << "\n\npoint: "; 32 point.print(); // static binding 33 cout << "\ncircle: "; 34 circle.print(); // static binding 35 36 // output objects point and circle using dynamic binding 37 cout << "\n\ninvoking print function on point and circle " 38 << "\nobjects with dynamic binding"; 39 40 // aim base-class pointer at base-class object and print 41 pointptr = &point; 42 cout << "\n\ncalling virtual function print with base-class" 43 << "\npointer to base-class object" 44 << "\ninvokes base-class print function:\n"; 45 pointptr->print();

37 39 Beispiel "Kreis": Testprogramm (3) Zusammenfassung virtuelle Methoden 47 // aim derived-class pointer at derived-class 48 // object and print 49 circleptr = &circle; 50 cout << "\n\ncalling virtual function print with " 51 << "\nderived-class pointer to derived-class object " 52 << "\ninvokes derived-class print function:\n"; 53 circleptr->print(); 54 55 // aim base-class pointer at derived-class object and print 56 pointptr = &circle; 57 cout << "\n\ncalling virtual function print with base-class" 58 << "\npointer to derived-class object " 59 << "\ninvokes derived-class print function:\n"; 60 pointptr->print(); // polymorphism: invokes circle's print 61 cout << endl; 62 63 return 0; Zur Laufzeit wird ermittelt, 64 65 // end main daß pointptr auf ein } Circle Objekt zeigt und die print-funktion von Circle wird aufgerufen. Dies ist ein Beispiel für Polymorphismus! stellen Polymorphismus zur Verfügung Gleiche "Mitteilung", hier draw, wird vielen verschiedenen Objekten gegeben alles durch Basiszeiger Mitteilung nimmt viele verschiedene Formen an Basiszeiger auf Basisobjekt, Zeiger von abgeleiteter Klasse auf abgeleitete Klasse: klar! Basiszeiger auf abgeleitetes Objekt: Es können nur Methoden der Basisklasse benutzt werden Zeiger von abgeleiteter Klasse auf Basisklasse: Syntaxfehler Programme sind leichter erweiterbar, da "neue" Klassen mit "alten" gleich behandelt werden Beispiel "Kreis": Programmausgabe 38 6.4 Abstrakte Klassen 40 Invoking print function on point and circle objects with static binding Point: [30, 50] Circle: Center = [120, 89]; Radius = 2.70 Invoking print function on point and circle objects with dynamic binding Calling virtual function print with base-class pointer to base-class object invokes base-class print function: [30, 50] Calling virtual function print with derived-class pointer to derived-class object invokes derived-class print function: Center = [120, 89]; Radius = 2.70 Abstrakte Klassen einziger Zweck: eine Basisklasse zu sein! sind unvollständig abgeleitete Klassen füllen Lücken Es können keine Objekte von diesen Klassen erzeugt werden ABER: Es können Zeiger und Referenzen von diesem Typ benutzt werden! Konkrete Klassen Objekte können davon erzeugt werden implementieren alle Funktionen, die deklariert werden Calling virtual function print with base-class pointer to derived-class object invokes derived-class print function: Center = [120, 89]; Radius = 2.70 Abstrakte Klassen sind nicht notwendig, aber nützlich

Abstrakte Klassen in C++ Benötigen mindestens eine rein virtuelle Methode Deklaration rein virtueller Methoden: virtual void draw() const = 0; Reguläre (=nicht reine) virtuelle Methoden besitzen Implementationen können überladen werden Rein virtuelle Methoden besitzen keine Implementation müssen überladen werden! Abstrakte Klassen können auch Daten und konkrete Methoden besitzen (eine Methode muß jedoch rein virtuell sein) Zeiger auf abstrakte Basisklassen sinnvoll für Polymorphismus 41 6.5 Virtuelle Destruktoren Problem: Was passiert, wenn ein Objekt mit delete zerstört wird, auf das über einen Basiszeiger zugegriffen wird? Einfache Lösung: deklariere Destruktor als virtuell! Dadurch werden alle Destruktoren von abgeleiteten Klassen virtuell und es wird immer der richtige ausgewählt Regel: sobald mindestens eine Methode virtuell ist, sollte auch ein virtueller (evtl. leerer) Destruktor erzeugt werden! Konstruktoren können nicht virtuell sein. Wieso nicht? 43 Beispiel für abstrakte Basisklasse Abstrakte Klasse Shape Definiert draw als rein virtuelle Methode Circle, Triangle, Rectangle sind von Shape als konkrete Klassen abgeleitet: Jede muß Methode draw überladen Bildschirmmanager weiß, daß jedes Objekt sich selbst zeichnen kann 42