4. Objektorientierte Programmierung mit C++

Ähnliche Dokumente
Überblick. Überblick zum weiteren Inhalt

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

8. Exkurs in die objektorientierte Programmierung: C++

Grundlagen der Informatik Vererbung von Klassen

Grundlagen der Informatik

4. Objektorientierte Programmierung mit C++

Überblick. 5. Objekt und Klasse, Elementfunktionen

4. Objektorientierte Programmierung mit C++

Überblick. 6. Konstruktor und Destruktor - obligatorische Elementfunktionen einer Klasse

8. Objektorientierung und C++

4. Objektorientierte Programmierung mit C++

4. Objektorientierte Programmierung mit C++

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

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

Einstieg in die Informatik mit Java

Programmieren in Java

Vererbung und Polymorphie

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

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

C++ - Objektorientierte Programmierung Vererbung

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren

Einstieg in die Informatik mit Java

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

Überblick. 7. Überladen von Operatoren

Grundkurs C++ IDE Klassenhierarchien

Grundkurs C++ IDE Klassenhierarchien

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

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

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

4. Objektorientierte Programmierung mit C++

Vererbung, Polymorphie

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

Von der UML nach C++

Vererbung und Polymorphie

11 Vererbung und Klassenhierarchie

Einführung in die Programmierung mit C++

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

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

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

Objektorientierte Programmierung mit C++ SS 2007

Neben der Verwendung von Klassen ist Vererbung ein wichtiges Merkmal objektorientierter

Java Vererbung. Inhalt

Exceptions und Vererbung

Mikrorechentechnik II. Klassen in C++

Prinzipien der objektorientierten Programmierung (OOP)

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

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

Vererbung. Generalisierung und Spezialisierung Vererbung und Polymorphismus

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 22

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

Einführung in das Objektorientierte Programmieren mit C++

3. Exkurs in weitere Arten der Programmierung

Kapitel 13. Abstrakte Methoden und Interfaces. Fachgebiet Knowledge Engineering Prof. Dr. Johannes Fürnkranz

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

3 Objektorientierte Konzepte in Java

01. Grundprinzipien der Vererbung

Programmierung und Angewandte Mathematik

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

Programmiertechnik Objektorientierung

Prof. Dr. Oliver Haase Karl Martin Kern Achim Bitzer. Programmiertechnik Objektorientierung

Inhaltsverzeichnis. Vorwort

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

Objektorientiertes Programmieren mit C++ für Fortgeschrittene

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

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

Java, OO und UML Fortsetzung

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

Fragen zur OOP in Java

Einstieg in die Informatik mit Java

7. Übung Informatik II - Objektorientierte Programmierung

Begriffe 1 (Wiederholung)

Objektorientierte Programmierung und Klassen

Objektorientiert in C++

Vererbung. Was versteht man unter dem Begriff Vererbung?

Objektorientiertes Programmieren

Objektorientierte Programmierung Studiengang Medieninformatik

Kapitel 6. Vererbung

Programmierkurs C++ Abstrakte Klassen und Methoden

Einführung in die Programmiersprache Java II

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

Objektorientiertes Programmieren in C++

Einstieg in die Informatik mit Java

Verwendung von Klassen in C++

Algorithmen und Datenstrukturen 06

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Repetitorium Informatik (Java)

Schlussendlich geben wir die Listen aus. Es kommt zu folgender Ausgabe:

Vorlesung Programmieren. Bisher: Klassen und Objekte. Was ist mit ähnlichen Klassen? Vererbung und Polymorphismus

Algorithmen und Datenstrukturen

Informationsverarbeitung im Bauwesen

Einführung in die Programmierung für NF. Vererbung

Kapitel 6. Vererbung

8. Objektorientierte Programmierung. Informatik II für Verkehrsingenieure

Methoden und Wrapperklassen

1. Grundlegende Eigenscha5en 2. Redefini+on 3. Polymophie 4. Mehrfachvererbung

Programmierkurs C/C++

Prof. W. Henrich Seite 1

Vererbung. Oberklassen und Unterklassen

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

4. Objektorientierte Programmierung mit C++

Transkript:

4. Objektorientierte Programmierung mit C++ Einführung C++ / Entwicklung/ Sprachfamilie Nicht objektorientierte Erweiterungen von C Grundlagen des Typkonzepts von C++ Ziele der Objektorientierung Objekt und Klasse, Elementfunktionen (Methoden) Konstruktoren, Copy-Konstruktor, Destruktor und Wertzuweisung Operatoren, Überladen von Operatoren Elementobjekte und Elementobjektkonstruktoren Klassenhierarchien und Vererbung Polymorphie Abstrakte Klassen Templates R. Grossmann, P. Sobe 1

Generalisierung und Spezialisierung (1) Verschiedene Klassen sind oft in einigen grundlegenden Eigenschaften/Funktionen gleich. Beispielsweise können verschiedene elektr. Bauelemente als Zweipole beschrieben werden. Generalisierung: Ohmscher Widerstand, Diode, Spule usw. sind Zweipole Spezialisierung: Vom Zweipol ausgehend erfolgt eine Spezialisierung als Ohmscher Widerstand durch ein lineares Strom/Spannungs-Verhältnis. als Diode durch eine Sperrfunktion und die Diodenkennlinie als Spule durch einen Induktiven Widerstand und ein phasenabhängiges Strom/Spannungsverhältnis ZP Generalisierung R.Grossmann, P. Sobe 2

Generalisierung und Spezialisierung (2) Gemeinsame Eigenschaften und Funktionen können in einer Basisklasse definiert werden. Eine Spezialisierung erfolgt durch Erzeugung einer neuen abgeleiteten Klasse, die die Eigenschaften und Funktion der Basisklasse erbt. Die abgeleitete Klasse kann Neues hinzufügen zusätzliche Elementobjekte und zusätzliche Methoden Die abgeleitete Klasse kann Methoden und Operationen verändern (überschreiben) Objekte der Basisklasse und abgeleiteter Klassen sind zuweisungskompatibel. R.Grossmann, P. Sobe 3

Begriff Klassenhierarchie Definition: Eine Menge von Klassen, deren Elemente durch die Relation Spezialisierung bzw. Generalisierung miteinander in Beziehung gesetzt sind, bezeichnet man als Klassenhierarchie, wenn jede Klasse höchstens eine Basisklasse besitzt. Basisklasse heißt eine Klasse von der durch Spezialisierung eine abgeleitete Klasse gebildet wurde. R.Grossmann, P. Sobe 4

Abgeleitete Klassen in C++ Programmen Abgeleitete Klassen müssen in C++ Programmen durch Angabe ihrer Basisklasse gekennzeichnet werden. Beispiel: class A {... //Basis-Klasse class B : public A{... //abgeleitete Klasse und gleich- // zeitig Basis-Klasse für C class C: public B{... //abgeleitete Klasse class D: public A{... //abgeleitete Klasse R.Grossmann, P. Sobe 5

Vererbbares und nichtvererbbares Inventar einer Klasse Alle Datenelemente einer Klasse, sowie alle Methoden mit Ausnahme der unten angegebenen werden an die abgeleitete Klasse vererbt. Nicht vererbt werden prinzipiell: - alle Konstruktoren - der Copy-Konstruktor - der Destruktor - der Zuweisungsoperator = R.Grossmann, P. Sobe 6

Zugriffsspezifizierer in Klassenhierarchien Alle privaten Datenelemente einer Klasse können nur von den Methoden der Klasse benutzt werden. Sollen diese Datenelemente auch von Methoden der abgeleiteten Klassen erreichbar sein, muss anstelle von private der Spezifizierer protected benutzt werden. Veranschaulichung: class myclass : public yourclass { public: myclass( ); ~myclass( ); // öffentlich für alle anderen Objekte, // auch für abgeleitete Klassen protected: double calculate( ); // nicht öffentlich, kann aber von Klasse // selbst und von abgeleiteter Klasse aufgerufen werden private: void internalaction( ); // nur von Klasse selbst aufrufbar, kein Zugriff durch // abgeleitete Klassen R.Grossmann, P. Sobe 7

Konstruktoren abgeleiteter Klassen Konstruktoren werden nicht vererbt. Konstruktoren abgeleiteter Klassen müssen den Konstruktor der Basisklasse aufrufen, der für die Instanziierung der geerbten Anteile sorgt. Beispiel: class A //Basis-Klasse { private: int i; public: A(int k){i=k;} //Konstruktor class B : public A //abgeleitete Klasse { private: char c; public: B(char s,int j): A(j) {c=s;} // : A(j) ruft Basisklassen-Konstruktor auf R.Grossmann, P. Sobe 8

Elementobjektkonstruktoren in Konstruktoren abgeleiteter Klassen Enthalten abgeleitete Klassen Elementobjekte, so müssen neben dem Konstruktor der Basisklasse auch der Elementobjekt- Konstruktor aufgerufen werden. Beispiel: class A { private: int i; public: A(int k){i=k;} //Basis-Klasse //Konstruktor class B : public A //abgeleitete Klasse { private: char c; A a; //Elementobjekt public: B(char s,int j,int m) //Konstruktor abgl. Klasse : a(m),a(j) {c=s;} // A(j) Basisklassen-Konstruktor // a(m) ist Aufruf Elementobjekt-Konstr. R.Grossmann, P. Sobe 9

Elementobjektkonstruktoren in Konstruktoren abgeleiteter Klassen Beachten Sie, dass unabhängig von der Notation die Rufreihenfolge festgelegt ist: 1. Ruf des Konstruktors der Basisklasse 2. Ruf des Elementobjekt-Konstruktors 3. Ruf des Konstruktors der abgeleiteten Klasse Beispiel: class A { //Basis-Klasse class B : public A //abgeleitete Klasse { private: int a, c; public: B(..., int m, int s, ) : a(m),a(j) {c=s;} // zuerst wird A(), dann a() und zuletzt B() ausgeführt R.Grossmann, P.Sobe 10

Grafische Veranschaulichung von Klassen (1) Klassen können untereinander verschiedene Beziehungen eingehen: Klasse B als Elementobjekt von Klasse A allgemein kann eine Klasse viele verschiedene Elementobjekte besitzen, die möglicherweise auch Instanzen verschiedener Klassen sind. Elementobjekte können ebenfalls aus verschiedenen Elementobjekten bestehen. Es ergibt sich eine Hierarchie von Elementen, die die Beziehung enthalten sein in wiederspiegeln. Klasse B als abgeleitete Klasse von A eine Klasse wird typischerweise von einer Basisklasse abgeleitet. Die Basisklasse kann wiederum eine abgeleitete Klasse sein. Es ergibt sich eine Schichtung im Sinne von erbt von. Mehrfachvererbung ist aber auch möglich, d.h. eine Klasse kann von mehreren Basisklassen erben. Klassen können sich über Referenzen assoziieren, d.h. Beziehungen aufbauen, die nicht durch die Elementobjekt-Beziehung abgedeckt ist. Diese Assoziation ist beim Entwurf zu berücksichtigen. Die grafische Darstellung der Hierarchien und Schichtung erfolgt durch Klassendiagramme, die als Teil der UML (Unified Modeling Language) vereinheitlicht wurden. R. Grossmann, P. Sobe 11

Grafische Veranschaulichung von Klassen (2) Objektorientierter Entwurf als Schritt, der vor der eigentlichen Programmierung erfolgt Einzelne Klasse in UML-Notation: Name der Klasse Elementobjekte Methoden Beispiel: Person name: String vorname: String alter: unsigned int anmelden() abmelden() R.Grossmann, P.Sobe 12

Grafische Veranschaulichung von Klassen (3) Vererbung: Zweipol BerechneU() spezialisiert OhmscherWiderst Diode BerechneU() BerechneU() R.Grossmann, P.Sobe 13

Grafische Veranschaulichung von Klassen (4) Komposition (Ganzes enthält Teile) ElektrSchaltung 1 1..* Zweipol Simuliere() BerechneU() Die Komposition durch Pfeil mit ausgefüllter Raute, wobei Teile nicht ohne das Ganze existieren können. In C++ wird die Komposition z.b. durch Elementobjekte realisiert. Am Pfeil sind Multiplizitäten vermerkt, die erklären, wie viele Objekte jeweils die Beziehung eingehen. Die Aggregation ist ähnlich, wobei Teile auch ohne das Ganze existieren dürfen. Fahrgemeinschaft 0..1 2..* Fahrgast Reise() Reise () R.Grossmann, P.Sobe 14

Grafische Veranschaulichung von Klassen (5) UML Assoziation eine inhaltliche Beziehung Konto 0.. * 1..* Kunde BucheAb() Kaufe() Klassen können Verweise (Zeiger, Referenzen) auf Objekte verwalten, um inhaltliche Beziehungen zu verwalten. R.Grossmann, P.Sobe 15

Objekte als Parameter (1) C++ erlaubt, Objekte als Parameter von Methoden zu übergeben. Beispiel: Eine Zeichenfläche (canvas), der verschiedene geometrische Objekte übergeben werden. Die Zeichenfläche kann diese Objekte beispielsweise unter Berücksichtigung von 3D- Überdeckungen zeichnen. class canvas { public: canvas() { } int register geom_obj(geomobj &o) { } void draw_all() { } class geomobj { public: geomob( ) { } int num_vertexes(); int get_vertex( int *x, int *y, int *y); int draw_vertex { } R.Grossmann, P.Sobe 16

Objekte als Parameter (2) Bei Übergabe von Objekten an Methoden sind die Mechanismen der Parameterübergabe zu beachten. Bei der Übergabe als Wert würde der Compiler eine lokale Kopie des übergebenen Wertes erzeugen. Dazu wird der Kopierkonstruktor aufgerufen. Dies ist oft nicht wünschenswert (Ressourcenverschwendung, Nebeneffekte). Das bei der Wertübergabe erzeugte Objekt würde wie andere lokale Objekte am Ende der Funktion gelöscht und der zugehörige Destruktor aufgerufen. Das führt i.d.r. zu unerwünschten Wirkungen. Im allgemeinen ist es daher sinnvoll, Objekte als (konstante) Referenz zu übergeben. R.Grossmann, P.Sobe 17

Objekte als Parameter (3) Übergabe von Objekten als Referenz an Methoden: int register geom_obj(geomobj &o) { for (int i=0; i<o.num_vertexes();i++) } o.get_vertex( &geobj[a].v[i].x, &geobj[a].v[i].y, &geobj[a].v[i].z ); besser noch als konstante Referenz: int register geom_obj(const geomobj &o) { R.Grossmann, P.Sobe 18

Friend - Klassen Eine Klasse kann eine andere als friend erklären. Damit erlaubt sie der anderen Klasse den Zugriff auf private Elemente und Methoden. class A { private: double wert; public: A(double x) {wert=x;} // Konstruktor friend class B; class B { double calculate( A a) { return a.wert*2.0; } Der friend-mechanismus durchbricht die Datenkapselung und sollte deshalb nur sparsam verwendet werden. R.Grossmann, P.Sobe 19

4. Objektorientierte Programmierung mit C++ Einführung C++ / Entwicklung/ Sprachfamilie Nicht objektorientierte Erweiterungen von C Grundlagen des Typkonzepts von C++ Ziele der Objektorientierung Objekt und Klasse, Elementfunktionen (Methoden) Konstruktoren, Copy-Konstruktor, Destruktor und Wertzuweisung Operatoren, Überladen von Operatoren Elementobjekte und Elementobjektkonstruktoren Klassenhierarchien und Vererbung Polymorphie Abstrakte Klassen Templates R. Grossmann / P. Sobe 20

Polymorphie in Klassenhierarchien Unter Polymorphie versteht man das dynamische Binden von Elementfunktionen. Damit wird erst zur Laufzeit festgestellt, welche Elementfunktion zu einer Klasse gehörig an einer bestimmten Stelle aufzurufen ist. Dies wird durch den Klassenkontext (Objekt) ermittelt. Der Normalfall ist die statische Bindung einer Elementfunktion zur Zeit der Übersetzung. D.h. der Compiler legt fest, welche Elementfunktion aufgerufen wird. Dadurch lässt sich bei Vererbung die Nutzung einer anderen, der Klassenzugehörigkeit des Objektes entsprechenden Elementfunktion nicht mehr erreichen. Die Auswahl der Bindungsverfahren einer Methode muss dem Compiler durch die Direktive virtual angezeigt werden. R.Grossmann, P. Sobe 21

Statisches Binden Beispiel: class A //Basis-Klasse { public: void Druck() {cout<< Klasse A ;} void Nachricht() {cout<< Nachricht von ; Druck() ;} class B : public A //abgeleitete Klasse { public: void Druck(){cout<< Klasse B ;} void main() { A a; B b; a.nachricht(); b.nachricht(); } Der Compiler bindet hier statisch den Aufruf der Methode Druck() ausgehend von Nachricht(). Die Druck-Methode ist bei der abgeleiteten Klasse überladen worden. Frage: Ruft b.nachricht(); damit automatisch die die überladene Druck-Methode auf? R.Grossmann, P. Sobe 22

Dynamisches Binden (1) Es wurde ausgegeben: Nachricht von Klasse A Nachricht von Klasse A Das ist korrekt, aber entspricht nicht der Intuition. Durch Einfügen der Compilerdirektive virtual wird jetzt dynamisches Binden erzwungen: class A //Basis-Klasse { public: virtual void Druck(){cout<< Klasse A ;} void Nachricht(){cout<< Nachricht von ; Druck() ;} class B : public A //abgeleitete Klasse { public: void Druck(){cout<< Klasse B ;} void main() {A a; B b; a.nachricht(); b.nachricht(); } Jetzt wird ausgegeben: Nachricht von Klasse A Nachricht von Klasse B R.Grossmann, P. Sobe 23

Dynamisches Binden (2) Der Compiler erzeugt ein dynamisches Binden über die sogenannte Virtual Address Table. Die Einsprungadresse der Methode wird dann zur Laufzeit ermittelt. Durch die Anwendung a.nachricht(); wird die Elementfunktion Druck() der Klasse A benutzt während bei Anwendung auf eine Objekt b.nachricht(); der Klasse B die Elementfunktion Druck() der Klasse B benutzt wird. R.Grossmann, P. Sobe 24

Dynamisches Binden und Polymorphie Durch virtuelle Funktionen wird ein s.g. polymorphes Laufzeitverhalten von Objekten erreicht. Polymorphie Vielgestaltigkeit Bei C++ bedeutet das: Objekte können über Zeiger vom Zeigertyp ihrer Basisklasse angesprochen werden, um z.b. deren Methoden aufzurufen. Es werden automatisch die Methoden der richtigen Klasse (jener, der das Objekt angehört) aufgerufen. Der Programmierer braucht bei der Programmerstellung nicht wissen, welche Klassenzugehörigkeit ein per Zeiger angesprochenes Objekt besitzt (vorausgesetzt das Objekt liegt innerhalb der Klassenhierarchie der Basisklasse). P. Sobe 25

Beispiel für Polymorphie (1) class B { public: B(int n): b(n) {} virtual void f() {cout << b;} private: int b; class C: public B { public: C(int n1, int n2): B(n1), c(n2) {} virtual void f() {B::f(); cout << c; } private: int c; class D: public C { public: D(int n1, int n2, int n3): C(n1,n2), d(n3) {} virtual void f() {C::f(); cout << d;} private: int d; int main { B* b_array[3]; B b(6); C c(9,12); D d (16,18,20); b_array[0] = &b; b_array[1] = &c; b_array[2] = &d; for(int i=0;i<3;i++) b_array[i]->f(); } R.Grossmann, P. Sobe 26

Beispiel für Polymorphie (2) b_array Ausgabe des Programms: B b(6) 6 9 12 16 18 20 C c(9,12) D d(16,18,20) Es reicht aus, den Typ der Basisklasse zu kennen und einheitliche Methodennamen für Basis- und abgleitete Klassen zu verwenden. Zur Laufzeit werden die Methoden der entsprechenden Objekte (Klassen) richtig ausgewählt, ohne dass sich der Programmierer darum kümmern muss. R.Grossmann, P. Sobe 27

Regeln für das Überschreiben von Methoden und Operatoren Nur virtuelle Methoden können sinnvoll überschrieben werden Sobald eine Methode einmal als virtuell deklariert wurde, bleibt sie für alle abgeleiteten Klassen virtuell Die Methodenköpfe (Methodenname, Rückgabewert und Parameterliste) müssen für alle sich ersetzende Methoden exakt übereinstimmen. Beispiel für gültiges und ungültiges Überschreiben: class A { public: virtual void f1(int x); virtual int f2(int x, int y); virtual int f3(const A& a); virtual A& f4(int x); class B: public A { public: virtual void f1(long x); // nein int f2(int x, int y); // ja int f3(a& a); // nein virtual B& f4(int x); // ja, nach // neuestem Standard R.Grossmann, P. Sobe 28

Heterogene Datenstruktur mittel Polymorphie class Zahl { public: virtual void Print () const { exit(99); // wird noch ueberschrieben } class Integer : public Zahl { int x; public: Integer (int i) { x = i;} virtual void Print() const { cout << x; } class Float : public Zahl { float x; public: Float (float i) { x = i;} virtual void Print() const { cout << x; } R.Grossmann, P. Sobe class Complex: public Zahl { double re,im; public: Complex (double r, double i) { } virtual void Print() const { cout << ( << re <<, << im << ) ; } // eine Datenstruktur mit mehreren // Zahlen, deren Typ gemischt ist. // Reihenfolge der Typen variabel int main() { Zahl *vec[10]; vec[0] = new Integer(4711); vec[1] = new Complex(12.2, 14.44); vec[2] = new Float(42.11); for (int i=0;i<3;i++) vec[i]->print(); 29