Programmierung III. Pointer für Fortgeschrittene Marc Ruberg. Arrays von Pointern ( Zeigervektoren ): Pointer auf Pointer:

Ähnliche Dokumente
Aufbau von Klassen. class punkt {...

Prof. W. Henrich Seite 1

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

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

11.3 Virtuelle Methoden

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

Repetitorium Informatik (Java)

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 3 - Objektorientierung

Einstieg in die Informatik mit Java

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

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

Informationsverarbeitung im Bauwesen

Einstieg in die Informatik mit Java

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

Vorkurs C++ Programmierung

Objektorientierte Programmierung mit Java. Grundlagen Übersicht. Programmiersprachen

C++ - Operatoren. Eigene Klassen mit neuen Funktionen

Java I Vorlesung Vererbung und Sichtbarkeit

Vorlesung Datenstrukturen

Kapitel 9: Klassen und höhere Datentypen. Klassen und höhere. Objekte, Felder, Methoden. Küchlin/Weber: Einführung in die Informatik

Kurzeinführung in C/C++ Elementare Datentypen in C++

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

Programmieren - Vererbung & Polymorphie

Anwendungsentwicklung mit Java. Grundlagen der OOP, Vererbung, Schnittstellen, Polymorphie

Vererbung. Was versteht man unter dem Begriff Vererbung?

Überschreiben von Methoden

Der Operator this. Wir betrachten nochmals die Klassendefinition von Ballon.

Java Einführung Methoden in Klassen

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

Programmieren in Java

Abend 7 Vererbung und Polymorphie, Abstrakte Klassen

Advanced Programming in C

Objektorientierte Programmierung OOP

Grundzüge der Programmierung. Wiederverwendung VERERBUNG

Einführung in C++ Vererbung und Polymorphismus

Verwendung von Klassen in C++

Übersicht. Vorstellung des OO-Paradigmas

Javakurs für Anfänger

Java Vererbung. Inhalt

Theorie zu Übung 8 Implementierung in Java

Überladen von Operatoren

1. Von der Idee zur Software 2. Funktionen und Datenstrukturen Lehrbuch: Organisation des Quellcodes 4. Werte- und Referenzsemantik

Präsentation Interfaces

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

Objektorientierte Programmierung

Deklarationen in C. Prof. Dr. Margarita Esponda

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Einführung in die. objektorientierte Programmierung

7 Vererbung. Modul Programmieren mit C++ Kapitel Vererbung

magnum C++ WALTER SAUMWEBER kompakt komplett kompetent

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

3 Objektorientierte Konzepte in Java

Pass by Value Pass by Reference Defaults, Overloading, variable Parameteranzahl

Beispiel: Zwischen der Oberklasse und der abgeleiteten Klasse besteht eine ist ein Beziehung. Eine abgeleitete Klasse stellt eine Spezialisierung der

Programmierung mit C Zeiger

Silke Trißl, Prof. Ulf Leser Wissensmanagement in der Bioinformatik. Jede Applikation braucht eine Klasse mit einer main-methode

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

Objektorientierte Programmierung mit C++ Zusammenfassung der wichtigsten Topics rund um die objektorientierte Programmierung mit C++11

01. Grundprinzipien der Vererbung

Inhaltsüberblick. I. Grundbegriffe - Objekte und Klassen. Organisatorisches. I. Grundbegriffe - Objektorientierte Konzepte

Klassenbeziehungen & Vererbung

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

Java Einführung Methoden. Kapitel 6

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

Probeklausur: Programmierung WS04/05

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

5.5.8 Öffentliche und private Eigenschaften

Angewandte Mathematik und Programmierung

Programmieren in C++ Überladen von Methoden und Operatoren

2. Semester, 2. Prüfung, Lösung

Beziehungen zwischen Objekten

C/C++-Programmierung

Angewandte Mathematik und Programmierung

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

Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Gute Lösung:

Teil 9: Vererbung. Prof. Dr. Herbert Fischer Fachhochschule Deggendorf Prof. Dr. Manfred Beham Fachhochschule Amberg-Weiden

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

Objektorientiertes Programmieren für Ingenieure

Die Programmiersprache C99: Zusammenfassung

Dynamischer Speicher

C++ - Eine Ubersicht fur Java-Programmierer

3. Semester : 1. Prüfung

Einführung in C++ mit Microsoft VS

Ulla Kirch Peter Prinz C+ + Lernen und professionell anwenden. mitp

Werner Achte rt DATA BECKER

Objektorientierte Programmierung

Einführung in den Einsatz von Objekt-Orientierung mit C++ I

AuD-Tafelübung T-B5b

Java, OO und UML Fortsetzung

Probeklausur: Programmierung WS04/05

Vererbung und Polymorphie

Ziel, Inhalt. Programmieren in C++ Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind

Programmieren II Vererbung. Programmieren II Vererbung. Programmieren II Vererbung. Programmieren II Vererbung. Einleitende Bemerkungen

Unterprogramme. Funktionen. Bedeutung von Funktionen in C++ Definition einer Funktion. Definition einer Prozedur

Übungspaket 29 Dynamische Speicherverwaltung: malloc() und free()

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

7. Objektorientierte Softwareentwicklung/3. Informatik II für Verkehrsingenieure

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Vererbung & Schnittstellen in C#

Einstieg in die Informatik mit Java

Transkript:

Programmierung III Marc Ruberg 1 Pointer für Fortgeschrittene Arrays von Pointern ( Zeigervektoren ): long *zahlenptr[25]; char *strptr[1000]; Pointer auf Pointer: char **sp Zeiger auf Funktionen: Typ (*funcptr)(parameterliste) Void (*functab[])(char*) 2 1

Lesekurs für komplexe Deklarationen Zuerst den Bezeichner suchen, der deklariert wird. Dann Folgendes wiederholen: 1. Nach rechts schauen! () oder [] interpretieren, falls vorhanden. 2. Steht rechts nichts oder ), dann links den Stern interpretieren. Zuletzt den Grundtyp interpretieren. Beispiel: char *(*(* test)())[22] 3 Leseaufgaben char (* strptr)[50] long * (* func())[] char * (*(*funcptr)())[] 4 2

Dynamische Variablen (1) Dynamische Variablen auf dem Heap 5 Dynamische Variablen (2) Direkt nach der Deklaration von anker: struct dyn_var *anker; 6 3

Dynamische Variablen (3) anker = (struct dyn_var *) malloc(sizeof(struct dyn_var)); 7 Dynamische Variablen (4) anker->key = 1; anker->next = (struct dyn_var *) malloc(sizeof(struct dyn_var)); 8 4

Dynamische Variablen (5) anker->next->key = 2; anker->next->next = NIL; 9 Dynamische Variablen (6) anker->next->next = anker; 10 5

Dynamische Variablen (7) anker = anker->next->next; 11 Dynamische Variablen (8) anker = anker->next; 12 6

Dynamische Variablen (9) anker = (struct dyn_var *) malloc(sizeof(struct dyn_var)); 13 Einfach verkettete Listen (1) Typdefinition des Listenknotens: typedef struct article2 { char name[21]; long num; struct article2 *next; } listelement; 14 7

Einfach verkettete Listen (2) Beispiel einer einfach verketteten Liste mit vier Elementen (schematische Darstellung): Die einzelnen Elemente können auf dem Heap dynamisch generiert werden dadurch wird nur so viel Speicherplatz belegt wie auch wirklich für die Daten benötigt wird 15 Einfach verkettete Listen (3) Eine einfach verketteten Liste mit vier Elementen und konkreten Daten. 16 8

Doppelt verkettete Listen Beispiel einer doppelt verketteten Liste mit vier Elementen (schematische Darstellung) Vorteile: Liste kann auch rückwärts durchlaufen werden Einfüge- und Löschoperationen werden dadurch einfacher 17 C++: Manipulatoren für die Ein- und Ausgabe Siehe Beispiele 18 9

Deklarationen in C++ Deklarationen sind an jeder beliebigen Stelle im Quelltext möglich, also auch z. B. for (int i = 1; i <= 10; i++) { cout << i << ". Schleifendurchlauf" << endl; } 19 inline-funktionen Geht auch mit C! inline int quadrat (int x) { return x*x; } Der Maschinencode wird kopiert (kein Unterprogramm) Wird zur Steigerung der Laufzeiteffizienz benutzt (in C gibt es hierfür die Makros). 20 10

Funktionen mit Defaultwerten Beispiel: void ausgabe (int wert, int basis = 10); Mögliche Aufrufe: ausgabe (17, 27); ausgabe (17); //gleichbedeutend mit // ausgabe (17, 10); Nicht möglich: ausgabe(); 21 Überladung Überladung von Funktionen (siehe ueberladen1.cpp) Operatoren: punkt operator+(punkt p1, punkt p2) { punkt ergebnis; } ergebnis.x = p1.x + p2.x; ergebnis.y = p1.y + p2.y; return ergebnis; 22 11

Scope-Resolution-Operator :: #include <iostream> using namespace std; int a = 1; // globale Variable; int main(void) { int a = 2; cout << "global: " << ::a << endl; cout << "lokal: " << a << endl; return 0; } 23 Referenzen auf Variablen Deklaration (immer mit gleichzeitiger Initialisierung!): int zahl; int& ref = zahl; Die Referenz ref ist nun ein Alias für die Variable zahl. Alle Operationen auf ref haben unmittelbare Auswirkung auf zahl: ref = 4711; Jetzt hat zahl ebenfalls den Wert 4711! 24 12

Referenzen als Parameter Verwendung von Referenzen als Parameter: void swap_referenz(int& a, int& b) { int tmp; tmp = a; a = b; b = tmp; } 25 Dynamische Speicherverwaltung in C++ Statt der Funktionen malloc() und free() werden die Operatoren new und delete verwendet: int* pzahl = 0; pzahl = new int; //alternativ: int* pzahl = new int;... delete pzahl; pzahl = 0; 26 13

Objektorientierte Programmierung Abstrakte Datentypen Klassen und Objekte Konstruktoren und Destruktoren 27 Abstrakter Datentyp Abstrakter Datentyp = Datentypen + Funktionen Vergleich: Zugriff auf zwei Koordinaten X und Y eines Punktes Unstrukturierter Zugriff: X = 100; Y = 0; 28 14

Abstrakter Datentyp (2) Strukturierter Zugriff: struct Punkt { int X, Y; }; void aendern(punkt& p, int x, int y) { p.x = x; p.y = y; } Punkt einpunkt; // Aufruf aendern(einpunkt, 10, 800); einpunkt.x = -3000; //??? 29 Abstrakter Datentyp (3) Kapselung, durch Programmiersprache unterstützt: Die Funktion als öffentliche Schnittstelle gehört zur Datenkapsel. Eine direkte Änderung der Daten unter Umgehung der Funktion ist unmöglich. Der ADT ist als Software-Baustein verwendbar. 30 15

Eigenschaften eines ADT: Der Sinn liegt darin, den richtigen Gebrauch der Daten sicherzustellen. Die tatsächliche Implementierung der Datenstrukturen ist nach außen nicht sichtbar. Logisch zusammengehörige Dinge sind an einem Ort konzentriert. Spezifikation ausschließlich durch die öffentliche Schnittstelle des ADT, die die mit ihm möglichen Operationen definert. Realisierung durch Klassen in der OOP. 31 Klassen und Objekte In C++ ist eine Klasse ein Datentyp, genauer: ein ADT. Für den Compiler ist eine Klasse eine Beschreibung später zu definierender Objekte. Ein Objekt ist die konkrete Ausprägung (Instanz) einer Klasse, es belegt Platz im Speicher. Ein Objekt hat eine Identität und einen Zustand. Der Zustand eines Objekts wird durch in der Klasse deklarierte Funktionen (Operationen, Methoden) geändert. 32 16

Deklaration einer Klasse in C++ class Klassenname { public: Typ Elementfunktion1(); Typ Elementfunktion2(); // und weitere... private: Typ Attribut1; Typ Attribut2; // und weitere... }; 33 Beispiel Klasse für einen Ort. Operationen: getx() = X-Koordinate zurückgeben gety() = Y-Koordinate zurückgeben aendern() = X- und Y-Koordinaten ändern Siehe COrt1.cpp, COrt1.h Die Implementierung der Methoden kann außerhalb der Klassendefinition geschehen (dies ist sogar der Normalfall! 34 17

Initialisierung und Konstruktoren Objekte können mit Konstruktoren während der Definition initialisiert, also mit sinnvollen Anfangswerten versehen werden. Konstruktoren haben keinen Return-Typ, auch nicht void. 35 Der Standardkonstruktor Der Standardkonstruktor hat keine Argumente Beispiel: Ort1::Ort1() { // neuer Standardkonstruktor xkoordinate = 0; // Koordinaten des ykoordinate = 0; // Nullpunkts } 36 18

Allgemeine Konstruktoren Allgemeine Konstruktoren können Argumente haben und überladen werden. Beispiel: Ort1::Ort1(int x, int y) { xkoordinate = x; ykoordinate = y; } 37 Allgemeine Konstruktoren (2) Aufruf des Konstruktors oder auch Definition des Objekts : Ort1 nocheinort(70, 90); Konstruktoren können auch überladen werden! 38 19

Allgemeine Konstruktoren (3) Elementinitialisierer: Membervariablen (bzw. Teilobjekte) können mit der Anweisung membervariable(anfangswert) initialisiert werden. Mehrere Elementinitialisierer können in einer durch Kommas getrennten Liste an die Definition des Konstruktors gehängt werden (siehe Beispiele). Dies gehört nicht in die Headerdatei! 39 Destruktoren Zweck: Aufräumarbeiten für nicht mehr benötigte Objekte Wenn Destruktoren nicht vorgegeben werden, werden sie vom System automatisch erzeugt. Der häufigste Zweck ist die Speicherfreigabe, wenn der Gültigkeitsbereich eines Objekts verlassen wird. Die Reihenfolge des Aufrufs der Destruktoren ist umgekehrt wie die der Konstruktoren. Destruktoren haben keine Argumente und keinen Rückgabetyp. 40 20

Destruktoren (2) Falls es globale Objekte gibt, wird ihr Konstruktor vor der ersten Anweisung von main() aufgerufen. Innerhalb des äußersten Blocks von main() definierte Objekte werden erst nach Verlassen von main() freigegeben. Wegen der umgekehrten Reihenfolge der Destruktoraufrufe werden globale Objekte zuletzt freigegeben. 41 Destruktoren (3) Beispiel: (siehe konstr_destr.cpp) class Beispiel { int zahl; public: Beispiel(int i = 0); // Konstruktor ~Beispiel(); // Destruktor }; Beispiel::Beispiel(int i) { // Konstruktor zahl=i; cout << "Objekt " << zahl << " wird erzeugt.\n"; } 42 21

Destruktoren (4) // globale Variable, durch Vorgabewert mit 0 initialisiert Beispiel ein_globales_beispiel; int main() { cout << "main wird begonnen\n"; Beispiel einbeispiel(1); { // neuer Block cout << " neuer Block\n "; Beispiel einbeispiel(2); cout << " Block wird verlassen\n "; } cout << "main wird verlassen\n"; } 43 Destruktoren (5) Ausgabe des Programms: Objekt 0 wird erzeugt. main wird begonnen Objekt 1 wird erzeugt. neuer Block Objekt 2 wird erzeugt. Block wird verlassen Objekt 2 wird zerstört. main wird verlassen Objekt 1 wird zerstört. Objekt 0 wird zerstört. 44 22

Vererbung Was ist Vererbung? Die von einer Basisklasse abgeleitete Klasse erbt die Membervariablen und Methoden. Zusätzlich können weitere Membervariablen und Methoden ergänzt werden. Wozu Vererbung? Datenabstraktion Wiederverwendbarkeit Beispiel: Ein Objekt vom Typ Pkw oder vom Typ Lkw ist ein spezielles Objekt der Klasse Kfz. 45 46 23

Vererbung (2) public-vererbung: public-elemente bleiben weiterhin public. Eine Methode der abgeleiteten Klasse kann nicht direkt auf private-elemente der Basisklasse zugreifen (aber indirekt via public-methoden der Basisklasse). Es stehen in der abgeleiteten Klasse zur Verfügung: Alle public-elemente der Basisklasse, die in der abgeleiteten Klasse zusätzlich definierten public-elemente. Mehrfache Vererbung: Eine abgeleitete Klasse kann selbst wieder Basisklasse für eine weitere von ihr abgeleitete Klasse sein. 47 48 24

49 Vererbung (3) Redefinition von Elementen: Jede Membervariable und jede Methode der Basisklasse kann in der abgeleiteten Klasse redefiniert werden. Redefinition bedeutet nicht Überladung: Redefinition entspricht einer abgeleiteten-klassenlokalen Definition (mit neuem Gültigkeitsbereich). Es kann auf gleichnamige public-elemente der Basisklasse mit dem Operator :: zugegriffen werden In der selben (abgeleiteten) Klasse können Methoden wie überall überladen werden (mehrfache Redefinition). 50 25

Vererbung (4) Konstruktoren abgeleiteter Klassen: Aufruf-Reihenfolge: Zuerst der Konstruktor der Basisklasse, dann der Konstruktor der abgeleiteten Klasse. Besonders effizient: Vermeidung von doppelter Initialisierung von Basisklassen-Membervariablen durch einen Basisinitialisierer. Auch (zusätzlich) möglich: Elementinitialisierer. Destruktoren abgeleiteter Klassen: Aufruf-Reihenfolge: Zuerst der Destruktor der abgeleiteten Klasse, dann der Destruktor der Basisklasse (automatisch). 51 Vererbung (5) protected-deklarationen: Falls erwünscht ist, dass die Methoden einer abgeleiteten Klasse auf Elemente der Basisklasse zugreifen, die nicht als public deklariert werden sollen, so können diese Elemente als protected deklariert werden. Auf protected-elemente kann von außen nicht zugegriffen werden (wie bei private-elementen). 52 26

Vererbung (6) protected-vererbung (eher selten...): Alle in der Basisklasse als public oder protected deklarierten Elemente werden in der abgeleiteten Klasse zu protected-elementen. private-vererbung (eher selten...): Alle in der Basisklasse als public oder protected deklarierten Elemente werden in der abgeleiteten Klasse zu private-elementen. Es können Ausnahmen für einzelne Elemente definiert werden (werden wir nicht weiter verfolgen). 53 Polymorphie Anforderung an die Programmiersprache: Es existiert ein Zeiger auf ein Objekt, von dem noch nicht feststeht, von welchem Typ (innerhalb einer Klassenhierarchie) es sein wird. Zur Programmlaufzeit soll nun entschieden werden, welche Methoden zum Einsatz kommen dürfen. Lösung: 1. Zeiger auf Objekt der Basisklasse 2. Virtuelle Methoden 54 27

Polymorphie (technische Realisierung) In der Basisklasse wird der virtuellen Methode das Schlüsselwort virtual vorangestellt, z. B. virtual void display() const; Bei der Redefinition dieser virtuellen Methode in der abgeleiteten Klasse muss Folgendes beachtet werden: gleiche Anzahl und gleiche Typen der Parameter, gleicher Ergebnistyp wie in Basisklasse. Konstruktoren können nicht virtuell sein. Destruktoren sollten immer virtuell sein, zwecks vollständiger Aufräumarbeiten bei dynamisch erzeugten Objekten. 55 Statische und dynamische Bindung Statische Bindung bedeutet, dass zum Zeitpunkt der Compilierung die Adresse einer Methode bereits bekannt ist. Statische Bindung liegt vor bei allen nicht-virtuellen Methoden, bei virtuellen Methoden, wenn die Methode direkt über einen Objektnamen (und nicht indirekt über einen Pointer) aufgerufen wurde. Bei dynamischer Bindung ist erst zur Laufzeit des Programms bekannt, welche Methode aufgerufen werden soll, z. B. bei: kfzptr->display(); 56 28

Realisierung der dynamischen Bindung Der Compiler realisiert die dynamische Bindung mit Hilfe von virtuellen Methodentabellen (Virtual Method Tables, VMT). Diese werden für jede Klasse angelegt, die mindestens eine virtuelle Methode enthält. Eine VMT ist ein Array mit den Adressen der virtuellen Methoden der jeweiligen Klasse. Jedes Objekt einer polymorphen Klasse besitzt einen (versteckten) Zeiger auf die VMT. Mit diesem Zeiger wird immer dann bei Bedarf (d. h. beim indirekten Aufruf über einen Basisklassenzeiger) die Adresse der virtuellen Methode bestimmt. 57 Virtuelle Methodentabelle 58 29

Dynamische Bindung: Pro und Contra Vorteil: Bereits übersetzter Quellcode kann nachträglich erweitert werden auch wenn dieser nicht vorliegt! So kann ein Programmierer eigene Klassen aus den Klassen von gekauften Klassenbibliotheken ableiten und eigene Versionen der virtuellen Methoden erstellen. Nachteile: VMTs belegen zusätzlichen Speicherplatz Programm ist etwas weniger performant 59 Unsichere Down-Casts Es ist ohne Compiler-Fehlermeldung möglich, einen Zeiger auf ein Objekt einer abgeleiteten Klasse in einen Zeiger auf ein Objekt einer anderen abgeleiteten Klasse zu casten: Pkw* pkwptr = (Pkw*)(kfzPtr); Eine Anweisung, die sich auf ein nicht vorhandenes Element bezieht, bringt allerdings das Programm zum Absturz, wie z. B. bei pkwptr->settyp("2cv"); (Falls pkwptr zur Laufzeit auf ein Objekt vom Typ Lkw zeigen würde.) 60 30

Cast-Überprüfung mit dynamic_cast<> Der Operator dynamic_cast<> liefert den Wert NULL zurück, falls versucht wurde, einen Zeiger in einen nicht-kompatiblen Objekttyp zu casten. Beispiel: Pkw* pkwptr = dynamic_cast<pkw*>(kfzptr); 61 Abstrakte Basisklassen Manchmal ist es zwar sinnvoll, dass eine Basisklasse wegen besserer Übersichtlichkeit einen logischen Oberbegriff darstellt, aber direkte Objekte dieser Basisklasse wären wenig nützlich. In einem solchen Fall möchte der Programmierer dem Compiler mitteilen, dass (mindestens) eine virtuelle Methode in einer abgeleiteten Klasse redefiniert werden muss. Man nennt eine solche Methode rein virtuell oder auch abstrakt. Eine Klasse, die eine rein virtuelle Methode enthält, wird ebenfalls als abstrakte Klasse bezeichnet. 62 31

Abstrakte Basisklassen (2) Syntax: virtual void Draw(HDC hdc) = 0; 63 friend-funktionen und friend-methoden Mitunter ist es wünschenswert, dass Funktionen, die nicht zu einer Klasse gehören, aber trotzdem sehr eng mit dieser Klasse zusammenarbeiten, einen Zugriff auf private-elemente der Klasse haben sollten. Dies ist insbesondere bei der Überladung von Operatoren der Fall und zwar aus Performance- Gründen. Die entsprechende Funktion muss in diesem Fall in der Klasse mit dem vorangestellten Schlüsselwort friend erwähnt werden. 64 32

friend-funktionen und friend-methoden Syntax: friend Euro operator* (double x, const Euro& e); Wenn die Implementierung der friend-funktion außerhalb der Klasse erfolgt, gibt es Fälle, bei denen dies mit dem Schlüsselwort inline geschehen sollte (z. B. bei Operatoren). 65 33