Jürgen Bayer. OOP mit C++ Von einfachen Klassen über Vererbung zum Polymorphismus

Größe: px
Ab Seite anzeigen:

Download "Jürgen Bayer. OOP mit C++ Von einfachen Klassen über Vererbung zum Polymorphismus"

Transkript

1 Jürgen Bayer OOP mit C++ Von einfachen Klassen über Vererbung zum Polymorphismus

2 Inhaltsverzeichnis 1 Einführung 1 1 Die Basis der OOP: Die Klasse Klassen und Strukturen Die Strukturierung einer Anwendung Einfache Klassen und deren Anwendung Grundlagen zur Programmierung von Klassen Objekte statisch erzeugen Objekte dynamisch erzeugen Die Bedeutung des Stack Wie werden Objekte gespeichert? Der this-zeiger Die Sichtbarkeit von Klassenelementen Daten schützen: Die Kapselung Die klassische Kapselung Bessere Kapselung mit Ausnahmen Konstruktoren und Destruktoren Konstruktoren Der Copy-Konstruktor Der Destruktor Assoziationen zwischen Objekten 20 2 Vererbung und Polymorphismus Vererbung Warum Vererbung? Das Beispiel Die Grundlagen der Vererbung Die Neudefinition von Methoden Verwenden geerbter Elemente Die Sichtbarkeit bei der Vererbung Veröffentlichen von privaten und geschützten Elementen in abgeleiteten Klassen Vererbung von Konstruktoren und Destruktoren 36

3 2.10 Polymorphismus und virtuelle Methoden public-, protected- und private-ableitung Mehrfachvererbung 42 3 OOP-Specials Abstrakte Klassen und Methoden Statische Klassenelemente Statische Eigenschaften (Klasseneigenschaften) Statische Methoden (Klassenmethoden) Verschachtelte Klassen Friends Operatoren für Klassen Schnittstellen 59 4 Index 64

4 Dieser Artikel beschreibt die grundlegenden Konzepte der objektorientierten Programmierung (OOP) in C++. Dabei gehe ich einen eher praxisorientierten als theoretischen Weg. In der OOP- Theorie wird vieles diskutiert, was in der Praxis wenig oder oft auch gar keine Bedeutung hat. Diese teilweise sehr theoretischen Themen lasse ich einfach weg. Trotzdem behandelt dieser Artikel die objektorientierte Programmierung recht ausführlich. Ich setze dabei voraus, dass Sie die Grundlagen der OOP und der normalen Programmierung (Variablen, Schleifen, Verzweigungen, Funktionen, Prozeduren etc.) einigermaßen beherrschen und nun die OOP in C++ kennen lernen wollen. Falls Sie die Grundlagen nicht kennen, lesen Sie meinen Online-Artikel OOP-Grundlagen ( In Kapitel 2 erfahren Sie, wie Sie eine Klasse programmieren und aus dieser Klasse Objekte erzeugen. Daneben werden wichtige Basiskonzepte der OOP (wie Kapselung, Konstruktoren und Destruktoren) näher beleuchtet. Ab Kapitel 3 geht es dann ans Eingemachte. Dieses Kapitel beschreibt zwei wichtige Konzepte der OOP, die so genannte Vererbung und den Polymorphismus. In Kapitel 4 werden schließlich einige spezielle Features der OOP, wie z. B. virtuelle Methoden, statische Klassenelemente und Schnittstellen beschrieben, die Sie kennen sollten, wenn Sie die Möglichkeiten der OOP wirklich ausnutzen wollen. Einführung 1

5 C++ erlaubt die Deklaration von Klassen und Strukturen zur Strukturierung eines OOP- Programms. Klassen und Strukturen unterscheiden sich in C++ prinzipiell kaum. In beiden können Sie Eigenschaften und Methoden unterbringen. Für einige Leser werden Methoden in Strukturen (die in klassischen Programmen nur Daten speichern) etwas ungewöhnlich sein. C++ definiert den Begriff Struktur aber etwas anders als gewohnt. Die folgende Auflistung macht die Unterschiede zwischen Klassen und Strukturen deutlich: Klassen werden mit dem Schlüsselwort class deklariert, Strukturen mit struct. Alle Datenfelder in einer Struktur sind öffentlich. Klassen ermöglichen dagegen, dass Datenfelder privat oder geschützt (protected) deklariert werden. Strukturen ermöglichen somit nicht das wichtige Konzept der Kapselung. Strukturen können eigentlich nur deswegen wie einfache Klassen behandelt werden, damit die Umsetzung von C-Quellcode nach C++ vereinfacht wird. Weil Strukturen die wichtige Kapselung nicht unterstützen, sollten Sie stattdessen immer Klassen einsetzen. Strukturen werden in diesem Artikel nicht weiter behandelt. Das folgende Beispiel deklariert eine Struktur zur Speicherung von Personendaten: struct Person /* Datenfelder der Struktur */ string Vorname; string Nachname; ; /* Eine einfache Methode, die den vollen Namen * der Person zurückgibt */ string VollerName() return Vorname + " " + Nachname; Instanzieren und Verwenden einer Struktur: Person p; p.vorname = "Fred Bogus"; p.nachname = "Trumper"; cout << p.vollername() << endl; Größere Programme erfordern eine Strukturierung des Quellcodes. Die Basis der Strukturierung ist in C++ eine Klasse. Über Klassen erreichen Sie, dass Sie Programmcode wiederverwenden können und dass Sie Ihr Programm so strukturieren, dass die Fehlersuche und die Wartung erheblich erleichtert werden. Wenn Sie eine Klasse entwickeln, können Sie entscheiden, ob Sie eine echte Klasse (mit normalen Eigenschaften und Methoden) programmieren, aus der Sie später Instanzen erzeugen, oder ob Sie eine Klasse mit statischen Methoden und Eigenschaften erzeugen wollen. Statische Methoden und Eigenschaften (Klassenmethoden, Klasseneigenschaften) können Sie auch ohne eine Instanz der Klasse aufrufen. Echte Klassen arbeiten echt objektorientiert, Klassen mit statischen Methoden und Eigenschaften simulieren (u. a.) die Module der strukturierten Programmierung. Die Basis der OOP: Die Klasse 2

6 ! "## $" In einer C++-Datei (mit der Endung.cpp) können Sie eine oder mehrere Klassen implementieren. In Visual Studio fügen Sie Ihrem Projekt dazu eine neue cpp-datei über den Befehl NEUE KLASSE im Menü EINFÜGEN hinzu. Visual Studio erzeugt allerdings schon eine cpp- und eine h-datei für die Klasse. Die h-datei (Headerdatei) enthält die Deklaration der Klasse, die cpp-datei enthält die Implementierung der Methoden der Klasse. Sie können Klassen jedoch auch komplett in der cpp- Datei unterbringen und auf die Headerdatei verzichten (indem Sie diese einfach aus dem Projekt entfernen). In einer cpp-datei können Sie eine oder mehrere Klassen unterbringen. In der einfachsten Variante werden die Methoden direkt in der Klasse implementiert: class Kreis /* Eigenschaften */ int Radius; ; /* Methoden */ double Umfang() return * 2 * Radius; double Oberflaeche() return * Radius * Radius; Die Klassendeklaration beginnt immer mit dem Schlüsselwort class, gefolgt vom Namen der Klasse. Das Schlüsselwort public definiert, dass die folgenden Klassenelemente öffentlich sind, also von außen, über eine Instanz dieser Klasse verwendet werden können. Eigenschaften werden wie Variablen, Methoden wie Funktionen deklariert. Methoden können auf alle Elemente einer Klasse zugreifen, wie es im Beispiel mit der Eigenschaft Radius der Fall ist. Wenn Sie ein Objekt dieser Klasse verwenden wollen, müssen Sie dieses Objekt nicht, wie in anderen Sprachen, explizit erzeugen. Eine einfache Deklaration reicht in C++ aus. C++ erzeugt das Objekt dann automatisch: int main(void) /* Variable der Klasse deklarieren, womit gleich * auch ein Objekt erzeugt wird */ Kreis k; /* Radius setzen */ k.radius = 20; /* Fläche berechnen und ausgeben */ cout << "Die Flaeche eines Kreises mit " << k.radius << " mm ist " << k.oberflaeche() << " mm^2"; In der Praxis werden Klassen oft in separaten Dateien deklariert, um diese einfach in anderen Programmen wiederverwenden zu können. Um eine oder mehrere Klassen aus separaten Dateien in ein C++-Programm einbinden zu können, können Sie zwei Wege gehen. Der einfachere ist der, die Die Basis der OOP: Die Klasse 3

7 komplette Klasse einfach in einer cpp-datei zu deklarieren und diese cpp-datei über die #include-anweisung einzubinden: #include <iostream.h> #include "Kreis.cpp" int main(void) Kreis k; k.radius = 20; cout << "Die Flaeche eines Kreises mit " << k.radius << " mm ist " << k.oberflaeche() << " mm^2"; Eine etwas kompliziertere Möglichkeit, Klassen in separaten Dateien zu verwalten, ist das Trennen der Deklaration von der Implementierung. Dazu erzeugen Sie eine Datei mit der Endung.h. Diese Headerdatei erhält denselben Namen wie die eigentliche cpp-datei und wird nur mit der Deklaration der Klasse versehen: /* Datei Kreis.h */ class Kreis int Radius; double Umfang(); double Oberflaeche(); ; Für die Implementierung erzeugen Sie eine gleichnamige Datei mit der Endung.cpp. Diese Datei enthält dann die Implementierung der Methoden. Um die Methoden der u. U. verschiedenen Klassen zu unterscheiden, wird jedem Methodenname der Klassenname, gefolgt von zwei Doppelpunkten, vorangestellt. Die Headerdatei muss in die cpp-datei eingebunden werden, damit der Compiler die zugehörige Klasse erkennen kann: /* Datei Kreis.cpp */ #include "Kreis.h" /* Implementierung der Methoden */ double Kreis::Umfang() return * 2 * Radius; double Kreis::Oberflaeche() return * Radius * Radius; Im eigentlichen Programm binden Sie dann nur die Header-Datei ein: #include <iostream.h> #include "Kreis.h" int main() Kreis k; k.radius = 20; cout << "Die Flaeche eines Kreises mit " << k.radius << " mm ist " << k.oberflaeche() << " mm^2"; Die Basis der OOP: Die Klasse 4

8 Diese Trennung macht dann Sinn, wenn Sie Ihre Klassen in Bibliotheken (mit der Endung.lib) kompilieren und diese Bibliotheken für die eigene Verwendung in einem separaten Ordner speichern. Wenn Sie diese Bibliotheken verwenden wollen, benötigt der Compiler Informationen darüber, welche Klassen und andere Typen in der Bibliothek vorhanden sind. Dazu wird dann die Headerdatei verwendet. Diese müssen Sie in alle Quellcodedateien einbinden, in denen Sie die Klassen (und andere Typen) der Bibliothek verwenden wollen. Wenn Sie eine Bibliothek anderen Programmierern zur Verfügung stellen wollen, müssen Sie auch die Headerdateien mitliefern, damit die anderen Programmierer die Bibliothek überhaupt verwenden können. Dasselbe machen Sie in Ihren C- und C++-Programmen, wenn Sie die Headerdateien der Standardbibliotheken in Ihre Programme einbinden. Die Funktionen, Strukturen, Klassen etc., die Sie dann in Ihren Programmen verwenden, sind üblicherweise in Bibliotheken gespeichert. %&! Statisch erzeugen Sie ein Objekt, indem Sie eine Objektvariable wie eine einfache Variable deklarieren: Kreis k; // statische Erzeugung Statisch bedeutet hier, dass C++ das Objekt auf dem Stack speichert. Der Stack ist ein Speicherbereich, den alle Programme besitzen und auf dem u. A. alle lokalen Variablen einer Funktion oder Methode gespeichert werden. Da der Stack nach der Ausführung der Funktion/Methode wieder automatisch bereinigt wird, werden statische Objekte also automatisch zerstört, wenn die Funktion bzw. Methode beendet ist. Diese statische Erzeugung ist übrigens eine Spezialität von C++. Andere Sprachen, wie Pascal/Delphi, C#, Visual Basic(.NET) und Java kennen keine statisch erzeugten Objekte. In diesen Sprachen werden Objekte immer dynamisch erzeugt. Das Problem bei statischen Objekten ist, dass Sie schon bei der Entwicklung wissen müssen, wie viele Objekte gespeichert werden sollen, weil Sie ja die entsprechende Anzahl an Variablen deklarieren müssen. Für manche Probleme reicht das aber nicht aus. Wollen Sie z. B. ein Programm erzeugen, das einen Stammbaum darstellen soll, können Sie bei der Entwicklung noch gar nicht wissen, wie viele Personen-Objekte der Anwender erzeugen und speichern will. Ein anderes Problem kann sein, dass Ihre Objekte sehr viel Speicher benötigen und so die Maximalgröße des Stack (per Voreinstellung 1 MB) überschritten werden kann. Deshalb ist es in C++ auch möglich, Objekte dynamisch zu erzeugen. %&'#! Für die dynamische Erzeugung von Objekten deklarieren Sie die Objektvariable als Zeiger: Kreis *k; Dann erzeugen Sie das Objekt über den new-operator: k = new Kreis; Dynamisch erzeugte Objekte werden auf dem Heap angelegt. Der Heap ist ein Speicherbereich, der für globale Daten reserviert ist. Auf dem Heap werden außerdem alle Funktionen und Klassen einer Anwendung gespeichert. Die Größe des Heap ist nur durch den im System verfügbaren Speicher begrenzt. So kann Ihre Anwendung während des Programmablaufs (eben dynamisch) nahezu beliebig viele Objekte erzeugen. Das Problem dabei ist lediglich, wie Sie die Objekte referenzieren, weil Sie zur Entwicklungszeit noch nicht wissen können, wie viele Referenzen Sie benötigen. Dafür existieren Die Basis der OOP: Die Klasse 5

9 aber einige einfach handhabbare Lösungen, wie z. B. dynamische Arrays oder Auflistungen (die im Rahmen dieses Artikels aber nicht beschrieben werden können). Objekte, die dynamisch erzeugt wurden, können über eine Dereferenzierung des Zeigers angesprochen werden: (*k).radius = 20; Durchgesetzt hat sich aber die Kurzschreibweise, die mit dem Operator -> arbeitet: k->radius = 20; Dynamisch erzeugt Objekte müssen Sie wie alle dynamisch reservierten Speicherbereiche über die delete-anweisung wieder aus dem Speicher entfernen. Vergessen Sie dies, bleibt das Objekt im Speicher, so lange Ihre Anwendung läuft, und verbraucht unnötig Ressourcen. delete k; ( Der Stack besitzt eine große Bedeutung für ein Programm. Der Stack ist ein spezieller Speicherbereich, den jedes Programm besitzt und der wie ein Stapel arbeitet: Daten werden der Reihe nach oben auf dem Stapel abgelegt und können auch wieder, der Reihe nach, vom Stapel entfernt werden. Der Stack wird (vom Compiler automatisch) über Funktionen angesprochen, die Daten oben auf dem Stapel ablegen, Daten vom Stapel auslesen und vom Stapel löschen. Auf dem Stack werden Daten abgelegt, die einen Funktions- oder Methodenaufruf betreffen. Beim Aufruf der folgenden Funktion, int Add(int x, int y) int result; result = x + y; return result; void main(void) int i = Add(1, 2); cout << I; legt der Compiler die folgenden Daten auf dem Stack an: einen Speicherbereich für den Rückgabewert der Funktion, die Adresse, zu der das Programm nach der Ausführung zurückspringen muss, die Argumente der Funktion, und die lokalen Variablen der Funktion. Abbildung 1.1 stellt den Stack bei der Ausführung der Funktion schematisch dar (der tatsächliche Aufbau hängt vom Compiler und der Aufrufkonvention von Funktionen / Methoden ab). Die Basis der OOP: Die Klasse 6

10 Abbildung 1.1: Der Stack bei der Ausführung einer Funktion Ruft die Funktion eine andere Funktion auf, werden die Daten für diese Funktion einfach oben auf dem Stack abgelegt. Beim Beenden einer Funktion wird der Stackbereich dieser Funktion wieder gelöscht. Was dann genau passiert, hängt vom Compiler und von der Aufrufkonvention der Funktion ab (die für ein Programm eingestellt werden kann). Schematisch können Sie sich den Vorgang folgendermaßen vorstellen: Die Funktion löscht alle Argumente und lokalen Variablen, liest die Rücksprungadresse aus, löscht diese und springt dann zu dieser Adresse zurück. Der Compiler sorgt dafür, dass der Rückgabewert der Funktion dann auch noch aus dem Stack ausgelesen und gelöscht wird, damit dieser in Ausdrücken verwendet werden kann. Der Stack besitzt immer eine festgelegte Maximalgröße. In Visual C++ ist die Voreinstellung (laut einigen Newsgroup-Artikeln 1 MB). Er wird allerdings zunächst mit 4 KB recht klein angelegt und bei Bedarf automatisch in 4 KB-Schritten vergrößert. Sie können die Maximalgröße des Stack und den Vergrößerungswert jedoch auch einstellen (Projekteigenschaften / Register LINK / Kategorie OUTPUT). Wenn zu viele Daten auf dem Stack abgelegt werden, was sehr schnell bei rekursiv aufgerufenen Funktionen / Methoden geschehen kann, resultiert ein Stack-Überlauf. ) * %&+, Wenn Sie wissen, wie Objekte prinzipiell gespeichert werden, können Sie einige Features der OOP, wie beispielsweise den Polymorphismus und virtuellen Methoden, besser verstehen. Eine Instanz einer Klasse besteht prinzipiell nur aus den Datenfeldern der Klasse (außer, wenn die Klasse Inline-Methoden beinhaltet, die innerhalb der Instanz gespeichert werden). Angenommen, ein Programm enthält die folgenden Klassen: Die Basis der OOP: Die Klasse 7

11 class Punkt int x; int y; void set(int x, int y) this->x = x; this->y = y; ; class Kreis int Radius; int Farbe; double Umfang return Radius * 2 * ; ; und erzeugt in main statische Instanzen dieser Klassen, void main(void) Kreis k1; Kreis k2; Punkt p1; k1.radius = 100; k1.farbe = 255; k2.radius = 200; k2.farbe = 1024; p1.set(10, 11); dann legt der Compiler im Stack nur die Werte der Eigenschaften Radius und Farbe der Kreise und die Werte der Eigenschaften x und y des Punktes an. Die Methoden der Klasse werden nur ein einziges Mal im Heap angelegt. Ein Methodenzeiger, der jeder Instanz einer Klasse beigefügt ist, zeigt auf die Adresse der Klasse. Abbildung 1.2: Schematische Darstellung der Speicherung von Objekten und deren Klassen k1, k2 und p1 sind also Variablen, die auf die Adresse zeigen, an der die Eigenschaften des Objekts gespeichert sind. Wenn Sie eine (Nicht-Inline-)Methode eines Objekts aufrufen, verwendet der Compiler den Methodenzeiger der Klasseninstanz und kann darüber die Startadresse der Methoden im Heap ermitteln. Dieses Vorgehen reduziert den Speicherbedarf von Objekten enorm. Die Basis der OOP: Die Klasse 8

12 -./ Damit eine Methode, die ja normalerweise (wenn es keine Inline-Methode ist), die Eigenschaften der aufrufenden Instanz bearbeiten kann, übergibt der Compiler der Methode ein zusätzliches, unsichtbares Argument, den this-zeiger. Dieser Zeiger zeigt auf die Objektinstanz, von der aus der Aufruf erfolgt ist. Wenn Sie in einer Methode auf Eigenschaften oder Datenfelder des Objekts zugreifen oder andere Methoden aufrufen, stellt der Compiler diesen Zeiger implizit vor den Namen des verwendeten Klassenelements, falls dies noch nicht explizit geschehen ist und falls ein entsprechendes Klassenelement gefunden wird. Die Methode Umfang der Kreis-Klasse des vorherigen Beispiels sieht im kompilierten Programmcode demnach so aus: double Umfang(Kreis *this) return this->radius * 2 * ; Über den this-zeiger können Sie immer explizit auf Klassenelemente zugreifen, auch dann, wenn innerhalb der Methode gleichnamige lokale Variablen oder Argumente existieren. Beachten Sie, dass this ein Zeiger ist. Sie müssen also mit einer Dereferenzierung oder mit dem Operator -> zugreifen. ( %$"# Die Elemente einer Klasse können Sie in der Sichtbarkeit einschränken, indem Sie diese Elemente in einen Block einfügen, der mit private:, protected: oder eingeleitet wird: class Demo private: // private Eigenschaften und Methoden protected: // geschützte Eigenschaften und Methoden // öffentliche Eigenschaften und Methoden Tabelle 1.1 beschreibt die Bedeutung der Sichtbarkeitsmodifizierer. Die Bedeutung des protected-blocks wird Ihnen aber wahrscheinlich erst bei der Vererbung klar. Modifizierer private Bedeutung Mit private stellen Sie die Sichtbarkeit eines Elements so ein, dass dieses nur innerhalb der Klasse gilt. Alle Methoden der Klasse können auf private Elemente zugreifen. Von außen können solche Elemente allerdings nicht verwendet werden. Wenn Sie damit eine Eigenschaft deklarieren, handelt es sich im Prinzip dabei um einfache Variablen, die von allen Methoden der Klasse verwendet, aber nicht von außen gesetzt oder gelesen werden können. protected Der Modifizierer protected kennzeichnet Klassenelemente, die zunächst wie private Eigenschaften auftreten, aber bei der Vererbung in abgeleiteten Klassen verwendet werden können (was bei privaten Elementen eben nicht möglich ist). public Elemente, die den Modifizierer public besitzen, können von außen (über eine Referenz auf ein Objekt dieser Klasse oder bei statischen Elementen über den Klassennamen) verwendet werden. Tabelle 1.1: Die Modifizierer für die Sichtbarkeit von Klassenelementen Die Basis der OOP: Die Klasse 9

13 )!+ Die Kapselung ist ein wichtiges Grundkonzept der OOP. Kapselung bedeutet, dass Objekte den Zugriff auf ihre Daten selbst kontrollieren. Besitzt ein Objekt nur einfache Eigenschaften, so kann es den Zugriff auf seine Daten nicht kontrollieren. Ein Programmierer, der dieses Objekt benutzt, kann in die Eigenschaften hineinschreiben, was immer auch zu dem Datentyp der Eigenschaften passt. Das kann dazu führen, dass das Objekt ungültige Daten speichert und damit u. U. beim Aufruf von Methoden fehlerhaft reagiert. Stellen Sie sich ein Objekt zum flexiblen Drucken von Texten und Grafiken vor. Dieses Objekt besitzt Eigenschaften zum Einstellen der Ränder, die beim Drucken berücksichtigt werden. Stellt der Programmierer diese Eigenschaften z. B. auf negative Werte ein, wird der Ausdruck wahrscheinlich etwas konfus aussehen. Kontrolliert das Objekt jedoch den Zugriff auf diese Eigenschaften, so ist ein fehlerhaftes Einstellen (wie z. B. auf negative Werte) erst gar nicht möglich. Das Objekt kann dann unter allen Umständen sicher arbeiten. Kapselung kann auf zwei Arten realisiert werden. Die ältere Methode ist, die Daten des Objekts einfach immer in privaten Variablen innerhalb der Klasse zu speichern und für den Zugriff auf diese Daten jeweils eine Methode zum Schreiben des Werts und eine zum Lesen des Werts zur Verfügung zu stellen. Diese Methoden können dann den Zugriff auf die Daten sehr gut kontrollieren. Eine andere, modernere Variante stellen einige Programmiersprachen zur Verfügung: Über so genannte Property-Prozeduren können Sie Eigenschaften implementieren, die nach außen wie eine normale Eigenschaft beschrieben und gelesen werden können, aber intern in Wirklichkeit aus einer Schreib- und einer Lesemethode bestehen. Der Vorteil einer solchen speziellen Eigenschaft ist, dass die Verwendung sehr einfach ist, weil einfach nur Werte hineingeschrieben und gelesen werden. Und trotzdem ist die Eigenschaft in der Lage, die geschriebenen oder gelesenen Daten zu kontrollieren. C++ kennt leider keine Property-Prozeduren, Sie müssen die Kapselung also über eigene Methoden implementieren. ) + Die klassische Kapselung arbeitet so, dass die Daten des Objekts grundsätzlich in privaten Variablen gespeichert werden und zum Zugriff auf diese Daten eine Lese- und eine Schreibmethode erzeugt werden. Die Schreibmethode kann entscheiden, welche Daten in das Objekt geschrieben werden, die Lesemethode entscheidet, wie die Daten zurückgegeben werden. Das folgende Beispiel demonstriert dieses Vorgehen für eine Personenklasse, die den Zugriff auf das Geburtsdatum der Person kontrolliert. Das folgende Beispiel implementiert eine Kreis-Klasse, die den Zugriff auf die Radius-Eigenschaft kontrolliert: class Kreis private: // der Radius int radius; // Methode zum Setzen des Radius void setradius(int wert) if (wert > 0) this->radius = wert; else this->radius = 0; // Methode zum Lesen des Radius int getradius() return this->radius; // Methode zur Berechnung des Umfangs double getumfang() Die Basis der OOP: Die Klasse 10

14 ; return this->radius * 2 * ; Die Kapselung ist in diesem Beispiel klar sichtbar an der Eigenschaft radius, deren Schreibmethode überprüft, ob der übergebene neue Radius größer als 0 ist. Die Lesemethode getradius macht zwar nichts weiter, als den Radius zurückzugeben, die zusätzliche Lesemethode getumfang demonstriert aber, dass es auch Sinn macht, den lesenden Zugriff auf die Daten zu steuern. ) + # # Etwas ungeschickt an dem vorherigen Beispiel ist, dass der aufrufende Programmierer nicht unbedingt mitbekommt, dass die Schreibmethode fehlgeschlagen ist, wenn er einen ungültigen Radius übergibt. Er erkennt dies höchstens daran, dass der Radius nun 0 beträgt, wenn die Methode einen ungültigen Radius zurückweist. Eine Methode, die den Zugriff auf die Daten kontrolliert, sollte dem Programmierer das Fehlschlagen der Methode aber so mitteilen, dass dieser gezwungen ist, das Fehlschlagen zu quittieren. Dafür stellen die verschiedenen Sprachen so genannte Ausnahmen (englisch: Exceptions) zur Verfügung, die der Entwickler der Klasse im Fehlerfall aufrufen kann und die dann im Programm zu einem Laufzeitfehler führen, wenn der Fehlerfall eintritt. Das folgende Beispiel demonstriert, wie in C++ eine Ausnahme ausgelöst wird: class Kreis private: // der Radius int radius; // Methode zum Setzen des Radius void setradius(int wert) if (wert > 0) this->radius = wert; else // Ausnahme "werfen" throw int(1001); ; // Methode zum Lesen des Radius int getradius() return this->radius; // Methode zur Berechnung des Umfangs double getumfang() return this->radius * 2 * ; Dieses Beispiel "wirft" eine Ausnahme vom Typ int. Beim Werfen einer Ausnahme wird eine Instanz eines Datentyps erzeugt und diese direkt (in den Klammern) initialisiert. Die Methode bricht an der Stelle, an der die Ausnahme geworfen wird, ab und gibt die Kontrolle an die aufrufende Methode/Funktion weiter. Diese kann die Ausnahme abfangen. Wird die Ausnahme dort nicht abgefangen, wird sie in der Aufrufreihenfolge weiter nach oben gereicht und kann dort Die Basis der OOP: Die Klasse 11

15 abgefangen werden. Wird eine Ausnahme schließlich nicht behandelt, führt das zur Anzeige einer Fehlermeldung und zum Absturz des Programms. Abgefangen werden Ausnahmen in try-catch-blöcken. Im try-block werden die Anweisungen untergebracht, die Ausnahmen erzeugen können, der catch-block fängt Ausnahmen ab. Sie können mehrere catch-blöcke einrichten, die verschiedene Typen von Ausnahmen abfangen. Das folgende Beispiel fängt Ausnahmen vom Typ int ab: int main(int argc, char* argv[]) // Kreis-Objekt erzeugen und verwenden Kreis k; // Die eventuelle Ausnahme wird abgefangen try k.setradius(-100); cout << "Ein Kreis mit " << k.getradius() << " mm Radius besitzt einen Umfang von " << k.getumfang() << " mm." << endl; catch (int i) cout << "Fehler Nummer " << i << endl; return 0; Ausnahmen sollten einen eigenen Typ besitzen, damit mehr als nur eine Fehlernummer ausgelesen werden kann. Für eine eigene Ausnahme benötigen Sie eine Klasse, die Sie allerdings schon mit einem Konstruktor erweitern müssen, damit beim Werfen der Ausnahme Werte übergeben werden können. Das folgende Beispiel deklariert eine Klasse WertAusnahme, die dann von der setradius- Methode geworfen wird, wenn der Radius ungültig ist: // Klasse für die Ausnahme class WertAusnahme string Meldung; int Nummer; ; // Der Konstruktor WertAusnahme(string meldung, int nummer) this->meldung = meldung; this->nummer = nummer; // Klasse für einen Kreis class Kreis private: // der Radius int radius; // Methode zum Setzen des Radius void setradius(int wert) if (wert > 0) this->radius = wert; else // Ausnahme "werfen" throw WertAusnahme("Der Radius kann nicht " + Die Basis der OOP: Die Klasse 12

16 "kleiner/gleich 0 sein", 1001); // Methode zum Lesen des Radius int getradius() return this->radius; // Methode zur Berechnung des Umfangs double getumfang() return this->radius * 2 * ; ; Beim Abfangen der Ausnahme kann nun zusätzlich eine Meldung ausgegeben werden: int main(int argc, char* argv[]) // Kreis-Objekt erzeugen und verwenden Kreis k; // Die eventuelle Ausnahme wird abgefangen try k.setradius(-100); cout << "Ein Kreis mit " << k.getradius() << " mm Radius besitzt einen Umfang von " << k.getumfang() << " mm." << endl; catch (WertAusnahme w) cout << "Fehler Nummer " << w.nummer << ": " << w.meldung << endl; return 0; Sie können mehrere catch-blöcke für unterschiedliche Ausnahmen hintereinander deklarieren. Wenn Sie in einem Block alle noch nicht abgefangenen Ausnahmen abfangen wollen, verwenden Sie die Syntax catch(...): try k.setradius(-100); cout << "Ein Kreis mit " << k.getradius() << " mm Radius besitzt einen Umfang von " << k.getumfang() << " mm." << endl; // Die Wert-Ausnahme abfangen catch (WertAusnahme w) cout << "Fehler Nummer " << w.nummer << ": " << w.meldung << endl; // Alle anderen Ausnahmen abfangen catch (...) cout << "Unbekannte Ausnahme aufgetreten." << endl; Wie Sie dem Beispiel entnehmen können, können Sie dann leider nichts weiter über die Ausnahme aussagen, als dass eine unbekannte Ausnahme eingetreten ist. Nun können Sie sich auch erklären, warum manche Programme solche unbekannten Ausnahmen oder Fehler meldet. Die Basis der OOP: Die Klasse 13

17 - " " " - " " Ein Konstruktor ist eine spezielle Methode, die automatisch aufgerufen wird, wenn das Objekt erzeugt wird. Auch wenn Sie keinen eigenen Konstruktor in die Klasse integrieren, besitzt diese immer einen Konstruktor: In Klassen, die keinen Konstruktor enthalten, fügt der Compiler automatisch einen parameterlosen Standardkonstruktor ein. Dieser Konstruktor wird implizit verwendet, wenn Sie eine Instanz einer Klasse ohne Argumente erzeugen: Kreis k; // Implizit wird der Standardkonstruktor verwendet Der vom Compiler eingefügte Standardkonstruktor besitzt für Programmierer nur die eine Bedeutung, dass Instanzen damit ohne Übergabe von Argumenten erzeugt werden können. Sie können aber auch eigene Konstruktoren in die Klasse implementieren, mit denen Sie ein Objekt direkt bei dessen Erzeugung initialisieren können. Bei einer Personenklasse wäre es z. B. sinnvoll, einem Personenobjekt bei der Erzeugung gleich den Vornamen und den Nachnamen der Person zu übergeben. In C++ wird ein Konstruktor ähnlich einer Methode deklariert. Weil ein Konstruktor allerdings nie einen Wert zurückgibt, wird kein Rückgabetyp angegeben (auch nicht void). Außerdem muss der Name des Konstruktors derselbe sein, wie der der Klasse. Konstruktoren müssen im public- Bereich der Klasse deklariert werden, damit diese von außen verwendet werden können. Konstruktoren können wie Methoden überladen werden. Das folgende Beispiel demonstriert dies anhand einer Klasse zur Speicherung von Personendaten: class Person string Vorname; string Nachname; string Ort; ; /* Dem ersten Konstruktor wird der Vorname und * der Nachname der Person übergeben */ Person(string vorname, string nachname) this->vorname = vorname; this->nachname = nachname; this->ort = ""; /* Dem zweiten Konstruktor wird zusätzlich * der Ort übergeben */ Person(string vorname, string nachname, string ort) this->vorname = vorname; this->nachname = nachname; this->ort = ort; Die Basis der OOP: Die Klasse 14

18 Wenn Sie nun Objekte dieser Klasse erzeugen, müssen Sie einen der beiden Konstruktoren verwenden: /* Eine Person mit dem ersten Konstruktor erzeugen */ Person p1("donald", "Duck"); /* Eine Person mit dem zweiten Konstruktor erzeugen */ Person p2 ("Fred Bogus", "Trumper", "New York"); Wenn Sie einen eigenen Konstruktor in eine Klasse einfügen, erzeugt der Compiler den Standardkonstruktor nicht mehr. Die Erzeugung einer Person ohne Übergabe von Argumenten ist in unserem Beispiel also nicht mehr möglich: Person p3; // lässt der Compiler nicht zu Wenn Sie dies zulassen wollen, müssen Sie einen parameterlosen Konstruktor in die Klasse einfügen: class Person string Vorname; string Nachname; string Ort; /* Parameterloser Standardkonstruktor */ Person()... Dieser Konstruktor muss nichts weiter an Quellcode enthalten. Konstruktoren besitzen normalerweise die Sichtbarkeit public, können aber auch im private oder protected-bereich deklariert werden. public-konstruktoren können als einzige von außen verwendet werden, um ein Objekt dieser Klasse zu erzeugen. Ein privater Konstruktor verhindert, dass ein Programm ein Objekt dieser Klasse mit Hilfe dieses Konstruktors erzeugt. Enthält die Klasse lediglich einen privaten Konstruktor, kann niemand (außer die Klasse selbst über eine statische Methode) von dieser Klasse Instanzen erzeugen. Üblicherweise wird ein solcher Konstruktor bei Klassen verwendet, die nur statische Elemente enthalten, und von denen deshalb keine Instanzen erzeugt werden sollen. private Konstruktoren verwendet man auch häufig in Zusammenhang mit friend- Deklarationen, um die Erzeugung eines Objekts von außen zu verhindern und nur von anderen Klassen aus zu ermöglichen. protected-konstruktoren verhalten sich ähnlich, können aber im Gegensatz zu privaten Konstruktoren von abgeleiteten Klassen in deren Konstruktoren aufgerufen werden. Mit privaten und geschützten Konstruktoren können Sie einige spezielle Techniken programmieren. So können Sie z. B. eine Instanzierung einer Klasse nur über eine statische Methode der Klasse ermöglichen, damit Sie die Anzahl der erzeugten Instanzen kontrollieren können. Konstruktoren werden nicht nur dazu verwendet, das Objekt zu initialisieren. Sie können in einem Konstruktor z. B. auch eine Datei oder eine Verbindung zu einer Datenbank öffnen, die Ihre Klasse benötigt. Das String-Beispiel beim Copy-Konstruktor demonstriert dies. Die Basis der OOP: Die Klasse 15

19 - 0"+'." " Jede C++-Klasse besitzt neben den normalen Konstruktoren auch einen Copy-Konstruktor. Ein Copy-Konstruktor besitzt ein Referenzargument vom Typ der Klasse und kopiert die Eigenschaften des übergebenen Objekts in die Eigenschaften der Instanz, für die der Copy-Konstruktor ausgerufen wird. Wenn Sie keinen eigenen Copy-Konstruktor in die Klasse integrieren, fügt der Compiler einen solchen automatisch ein (der aber zu Problemen führen kann, wie Sie gleich noch sehen). Der Copy-Konstruktor wird implizit verwendet, wenn Sie eine Instanz einer Klasse auf eine Variable zuweisen: // Eine Person über den Copy-Konstruktor erzeugen Person p2 = p1; // hier wird der Copy-Konstruktor aufgerufen Der Compiler erzeugt dann eine Kopie des Objekts. Nach der Ausführung dieser Anweisung existieren zwei Person-Objekte, die zwar dieselben Werte speichern, aber dennoch separate, individuelle Objekte sind. Das unterscheidet C++ von anderen Sprachen, die nur dynamische Objekte kennen. Wenn Sie in einer anderen Sprache eine Objektvariable einer anderen zuweisen, wird die Referenz kopiert, nicht die Werte. In diesen Sprachen würde nach der Ausführung der Anweisung im Beispiel oben beide Variablen dasselbe Objekt referenzieren! Wenn Sie in C++ allerdings Objekte dynamisch erzeugen und einen Objektzeiger einem anderen zuweisen, wird der Copy-Konstruktor nicht aufgerufen: // Eine Person dynamisch erzeugen... Person *p3 = new Person("Merril", "Overturf", "Wien"); //... und einer anderen Referenz zuweisen. // Der Copy-Konstruktor wird nicht aufgerufen Person *p4 = p3; Nach der Ausführung der letzten Anweisung zeigen beide Zeiger auf dasselbe Objekt. Eine Veränderung des Objekts über p3 betrifft dann auch p4. Über einen direkten Aufruf des Copy-Konstruktors können Sie auch dynamisch Kopien von Objekten erzeugen: Person *p5 = new Person(p1); // direkter Aufruf des Copy-Konstruktors Merken können Sie sich, dass immer, wenn Sie ein Objekt an eine Variable oder an ein Argument übergeben, die keine Zeiger und keine Referenzen sind, der Copy- Konstruktor aufgerufen und folglich eine Kopie des Objekts erzeugt wird. Diese Kopie wird auch als flache Kopie bezeichnet (das Kopieren der Referenzen heißt tiefe Kopie). Die Basis der OOP: Die Klasse 16

20 Wenn Sie eine Methode deklarieren, die ein Objekt als Argument besitzt, wird das Objekt über den Copy-Konstruktor kopiert, wenn das Argument nicht als Zeiger oder Referenz deklariert ist: void Demo1(Person p) // Der Copy-Konstruktor erzeugt eine Kopie // Eine Veränderung des Objekts wird natürlich // dann nicht nach außen gegeben p.vorname = "Donald"; p.nachname = "Duck"; cout << "p in der Funktion Demo2: " << p.vorname << " " << p.nachname << endl; Veränderungen des Objekts innerhalb der Funktion/Methode werden dann natürlich nicht im übergebenen Objekt sichtbar. Ist das Argument allerdings als Zeiger oder Referenz deklariert, wird keine flache Kopie erzeugt: void Demo2(Person &p) // Eine Veränderung des Objekts wird // nach außen gegeben p.vorname = "Donald"; p.nachname = "Duck"; cout << "p in der Funktion Demo2: " << p.vorname << " " << p.nachname << endl; Eine Veränderung des Objekts betrifft dann auch das übergebene Objekt. Sie können einen eigenen Copy-Konstruktor in Ihre Klassen einfügen. Dieser erhält als einziges Argument eine Referenz auf eine Instanz der Klasse: Person(Person &p) this->vorname = p.vorname; this->nachname = p.nachname; this->ort = p.ort; cout << "Copy-Konstruktor wurde aufgerufen." << endl; Sinnvoll ist dies immer dann, wenn Ihre Klassen mit dynamischen Speicherbereichen arbeiten. Der Default-Copy-Konstruktor erzeugt nur eine einfache Kopie der Daten der Klasse. Dabei werden nur die Zeiger der dynamischen Speicherbereiche kopiert. Das führt eigentlich immer zu Problemen. Das folgende Beispiel demonstriert diese Problematik. Eine eigene String-Klasse soll Zeichenketten verwalten: class String private: char *c_str; // Methode zum Setzen void setstring(const char *neuerstring) if (c_str!= NULL) delete c_str; c_str = new char[strlen(neuerstring) + 1]; strcpy(c_str, neuerstring); // Default-Konstruktor String() // Der C-String-Zeiger wird auf einen wohldefinierten Wert // gesetzt, der vor der Manipulation des Strings abgefragt Die Basis der OOP: Die Klasse 17

21 // werden kann. c_str = NULL; ; // Konstruktor mit C-String-Argument String(char *neuerstring) c_str = NULL; // wird von setstring abgefragt! setstring(neuerstring); // Destruktor virtual ~String() // Freigabe des Speichers if (c_str!= NULL) delete c_str; // Methode zum Lesen. // Diese Methode ist mit dem Modifizierer const versehen, // damit der gespeicherte C-String nicht über den // zurückgegebenen Zeiger verändert werden kann. // Das vermeidet eventuelle Probleme, die bei einer // Erweiterung der Klasse ansonsten auftreten könnten. const char *getstring() return c_str; Wenn nun ein Objekt dieser Klasse über den Copy-Konstruktor erzeugt wird, zeigt der char- Zeiger in beiden Instanzen auf denselben Speicherbereich: void main(void) String *s1 = new String("Hello Copy-Konstruktor-Problem"); // Copy-Konstruktor wird aufgerufen String *s2 = new String(*s1); cout << "String 1: " << s1->getstring() << endl; cout << "String 2: " << s2->getstring() << endl; Wird nun einer der beiden Strings gelöscht, delete s1; so zeigt der zweite String auf einen ungültigen Speicherbereich cout << "String 2 nach dem Löschen von String 1: " << s2->getstring() << endl; und gibt nur noch Speichermüll aus. Um dieses Problem zu vermeiden müssen Sie bei allen Klassen, die dynamischen Speicher anfordern und verwenden, einen Copy-Konstruktor erzeugen, der neben der Kopie der statischen Daten der Klasse den dynamischen Speicher für die neue Instanz separat reserviert und dessen Inhalt kopiert. Die Basis der OOP: Die Klasse 18

22 Bei der String-Klasse könnte dieser Konstruktor so aussehen: String(String &quelle) // Den Zeiger auf den C-String der übergebenen Instanz // zwischenspeichern, damit die Methode getstring nur // einmal aufgerufen werden muss. const char *temp = quelle.getstring(); // Überprüfen, ob die übergebene Instanz auch einen // gültigen String verwaltet if (temp!= NULL) // Kopieren des C-Strings in einen eigenen, // neuen Speicherbereich c_str = new char[strlen(temp) + 1]; strcpy(c_str, temp); else // die übergebene Instanz verwaltet keinen String; // den String-Zeiger auf einen definierten Wert setzen c_str = NULL; Die Überprüfung, ob die übergebene String-Instanz einen gültigen String verwaltet, ist notwendig. Ein Programmierer kann eine Instanz dieser Klasse auch über den Default-Konstruktor erzeugen: String s1; und diese Instanz einer anderen zuweisen: String s2 = s1; Ohne die Überprüfung würde der Copy-Konstruktor versuchen, die Länge des C-Strings zu ermitteln und dort mit einer Speicherverletzung abstürzen (weil der Zeiger des C-Strings NULL speichert). Die Basis der OOP: Die Klasse 19

23 - " Der Destruktor eines Objekts wird aufgerufen, wenn das Objekt zerstört wird. Im Destruktor können Sie Aufräumarbeiten vornehmen. Wenn Sie im Konstruktor Speicher reserviert oder Dateien geöffnet haben, geben Sie diese Ressourcen im Destruktor wieder frei. Eine Klasse kann nur einen Destruktor besitzen. Dieser wird ähnlich einem Konstruktor deklariert, lediglich mit einer vorangestellten Tilde. Den Destruktor sollten Sie in C++ immer virtuell deklarieren. Damit stellen Sie sicher, dass der Compiler auch dann den Destruktor der Klasse aufruft, wenn die Klasse in Programmen eingesetzt wird, die mit Polymorphismus arbeiten. Polymorphismus beschreibe ich in Kapitel 3, dann gehe ich auch noch einmal auf Destruktoren ein. Merken Sie sich hier nur, dass Sie den Destruktor in C++ immer mit virtual deklarieren sollten. Das String-Beispiel bei der Besprechung des Copy-Konstruktors hat bereits einen Destruktor verwendet, der den reservierten Speicherbereich freigibt: // Destruktor virtual ~String() // Freigabe des Speichers if (c_str!= NULL) delete c_str; 1 "!"!%& Objekte können Beziehungen untereinander aufbauen. Dabei wird ein Objekt über eine Eigenschaft eines anderen Objekts referenziert. Eine Person besitzt beispielsweise je eine Eigenschaft Vater und Mutter, die jeweils andere Person-Objekte referenzieren. Assoziationen können einseitig gerichtet sein (eine Person hat eine Mutter und einen Vater) oder auch doppelseitig (eine Person hat einen Vater und eine Mutter, Vater und Mutter referenzieren ihre Kinder). Eine besondere Form der Assoziation ist die Aggregation. Hierbei verhalten sich die Objekte wie ein Ganzes zu seinen Teilen. Ein Auto-Objekt besitzt beispielsweise eine Beziehung zu einem Motor-Objekt, ohne das das Auto nicht funktionieren könnte. Bei der normalen Assoziation sind die Objekte normalerweise gleichberechtigt. Ein Objekt kann auch ohne assoziierte Objekte existieren. Bei einer Aggregation ist das nicht der Fall: Das "Haupt"- Objekt kann ohne seine "Teil"-Objekte nicht (sinnvoll) existieren. Wenn Sie eine Instanz einer anderen Klasse innerhalb einer anderen Klasse statisch erzeugen wollen (das wäre ein Beispiel für eine Aggregation), sind Assoziationen sehr einfach. Das folgende Beispiel deklariert eine Punkt-Klasse, die in einer Kreis-Klasse verwendet wird. Die Punkt-Klasse kapselt den Zugriff auf die Daten, sodass keine ungültigen Punkte eingegeben werden können: Die Basis der OOP: Die Klasse 20

24 class Punkt private: int x; int y; // Methoden zum Setzen der Koordinaten void setx(int x) if (x >= 0) this->x = x; else this->x = 0; // Hier müsste eigentlich eine Ausnahme generiert werden ; void sety(int y) if (y >= 0) this->y = y; else this->y = 0; // Hier müsste eigentlich eine Ausnahme generiert werden // Methoden zum Lesen der Koordinaten int getx() return this->x; int gety() return this->y; Die Basis der OOP: Die Klasse 21

25 Die Kreis-Klasse schließt eine Punkt-Instanz für Ihre Position ein: class Kreis private: int radius; // Objekteigenschaft vom Typ Punkt Punkt Position; ; // Methode zum Setzen des Radius void setradius(int radius) if (radius > 0) this->radius = radius; else this->radius = 0; // Hier müsste eigentlich eine Ausnahme generiert werden // Methode zum Lesen des Radius int getradius() return this->radius; // Methode zur Berechnung des Umfangs double getumfang() return Radius * 2 * ; Der Punkt wird statisch innerhalb der Kreis-Klasse erzeugt und existiert damit automatisch, sobald eine Instanz der Kreis-Klasse erzeugt wird. Die Verwendung ist einfach: Kreis k; k.position.setx(10); k.position.sety(20); k.setradius(100); Statische Unterobjekte werden immer im Speicherbereich des umschließenden Objekts gespeichert. Die Basis der OOP: Die Klasse 22

26 C++ erzeugt die enthaltenen statischen Objekte einer Klasse immer bevor der Konstruktor der Klasse abgearbeitet wird. Sie können die Unterobjekte also im Konstruktor der Klasse initialisieren. Sie können dies einmal über einfache Zuweisungen an die Eigenschaften der Unterobjekte programmieren: // Klasse für einen Kreis class Kreis private: int radius; // Objekteigenschaft vom Typ Punkt Punkt Position; // Konstruktor, dem der Radius und die Position übergeben wird Kreis(int x, int y, int radius) this->position.setx(x); this->position.sety(y); this->radius = radius;... Wenn Sie zur Initialisierung den Konstruktor des Unterobjekts aufrufen wollen, müssen Sie diesen durch einen Doppelpunkt getrennt an den Kopf des Konstruktors der umschließenden Klasse anhängen: class Punkt private: int x; int y; // Konstruktor Punkt(int x, int y) // Aufruf der Methoden zum Setzen, da // diese die übergebenen Werte auf // Gültigkeit überprüfen setx(x); sety(y)... class Kreis private: int radius; // Objekteigenschaft vom Typ Punkt Punkt Position; // Konstruktor, dem die Position und der Radius übergeben wird // Der Konstruktor der Punkt-Klasse wird in der // Initialisierungsliste // des Kreis-Konstruktors aufgerufen, um den Punkt zu // initialisieren Kreis(int x, int y, int radius): Position(x, y) this->radius = radius;... Die Basis der OOP: Die Klasse 23

27 Statische Unterobjekte können nicht vom Typ der umschließenden Klasse sein. Wenn Sie Unterobjekte vom selben Typ wie dem der umschließenden Klasse in eine Klasse einbinden wollen, müssen Sie Zeiger oder Referenzen verwenden. Manchmal muss eine Objekteigenschaft dynamisch, bei oder nach der Erzeugung des Objekts, von außen gesetzt werden. Meist tritt dieser Fall bei normalen Assoziationen ein, bei denen ein Objekt auch ohne seine referenzierten "Partner"-Objekte existieren kann. Bei einem Stammbaum ist dies beispielsweise der Fall: Die Eigenschaft Vater und Mutter einer Person können erst gesetzt werden, wenn die Person erzeugt wird oder wurde. Sie können dazu ganz einfach Zeiger einsetzen: class Person string Vorname; string Nachname; ; // Zeiger für den Vater und die Mutter Person *Vater; Person *Mutter; // Methode zur Rückgabe des vollen Namens string VollerName() return Vorname + " " + Nachname; // Konstruktor Person(string vorname, string nachname, Person *mutter, Person *vater) this->vorname = vorname; this->nachname = nachname; this->mutter = mutter; this->vater = vater; int main(int argc, char* argv[]) // Einige Personen erzeugen und einen kleinen // Stammbaum aufbauen Person p1("anna", "Müller", NULL, NULL); Person p2("hans", "Weber", NULL, NULL); Person p3("gabi", "Müller", &p1, &p2); Person p4("pascal", "Müller", &p1, &p2); Person p5("natalie", "Sparks", NULL, NULL); Person p6("monika", "Müller", &p4, &p5); // Die Großmutter von p6 ermitteln if (p6.mutter!= NULL && p6.mutter->mutter!= NULL) cout << "Die Großmutter von " << p6.vollername() << " ist " << p6.mutter->mutter->vollername() << endl; return 0; Das Beispiel übergibt im Konstruktor der Personenklasse einfach NULL, wenn die Person keinen Vater oder keine Mutter hat. Beim Zugriff müssen Sie natürlich beachten, dass ein Zeiger auch auf NULL zeigen kann. Das Beispiel überprüft vor der Ausgabe des Namens der Großmutter, ob diese überhaupt existiert und nutzt dabei die Tatsache, dass C++ logische Ausdrücke von links nach rechts auswertet und die Auswertung abbricht, wenn ein Teilausdruck false ergibt. Die Basis der OOP: Die Klasse 24

28 Die Idee, statt der Zeiger einfach Referenzen zu verwenden (damit die Referenzierung / Dereferenzierung entfällt), kann in C++ leider nicht umgesetzt werden. Referenzen müssen in C++ immer direkt bei der Deklaration mit einer Instanz des Typs der Referenz initialisiert werden. Schade. Die Basis der OOP: Die Klasse 25

29 2% "'#"+# 2% Die Vererbung ist, neben der Kapselung, ein weiteres, sehr wichtiges Grundkonzept der OOP. Über die Vererbung können Sie neue Klassen erzeugen, die alle Eigenschaften und Methoden von einer Basisklasse, die bei der Erzeugung der neuen Klasse angegeben wird, erben. So können Sie sehr einfach die Funktionalität einer bereits vorhandenen Klasse erben, erweitern und/oder neu definieren. Das Erweitern einer Klasse ist nicht besonders schwierig: Sie implementieren dazu einfach weitere Eigenschaften und Methoden in der neuen Klasse. Neue Methoden können dabei auch geerbte Methoden aufrufen, womit Sie die in der Regel getestete und für gut befundene Funktionalität der Basisklasse auf einfache Weise wiederverwenden können. In diesem Sinne wird die Vererbung häufig für Programme genutzt, bei denen eine Basisfunktionalität in mehreren, unterschiedlichen Klassen vorhanden sein soll. Aber auch das so genannte Überschreiben geerbter Methoden mit einer neuen Programmierung ist möglich. So können Sie neue Klassen erzeugen, die im Prinzip genauso verwendet werden wie die Basisklasse, die aber ihren Job anders erledigen. Diese beiden Grundkonzepte der Vererbung, das Erweitern und Überschreiben, werden häufig gemeinsam genutzt. Die Vererbung wird in der Praxis für eigene Klassen nur relativ selten eingesetzt. Ein Grund dafür ist, dass relativ selten wirklicher Bedarf für Vererbung besteht. Ein anderer Grund ist, dass Programme, die Vererbung sehr intensiv nutzen, meist sehr unübersichtlich und dann auch fehleranfällig werden. Wenn Sie aber echt objektorientierte Programmiersprachen, wie z. B. Java und C# verwenden, kommen Sie ohne die Vererbung nicht aus. Diese Sprachen stellen Ihnen viele Programm- Komponenten in Form von Klassen zur Verfügung, die aber erst erweitert werden müssen, bevor sie sinnvoll verwendet werden können. Wenn Sie z. B. in Java ein Windows-Fenster für Ihre Anwendung benötigen, leiten Sie eine neue Klasse von der Java-Klasse Frame ab. Die Klasse Frame liefert nur ein einfaches Fenster, das noch um die benötigten Fensterelemente (wie Schalter, Textfelder etc.) erweitert werden muss. Ohne Vererbung könnten Sie die Frame-Klasse nicht erweitern und müssten immer mit einfachen Fenstern ohne weitere Elemente arbeiten. * #2%, Die wichtigen Punkte bei der Vererbung sind: die Wiederverwendung von Programmcode, die Wartbarkeit von Programmen und der über die Vererbung erreichte Polymorphismus. Den Polymorphismus beschreibe ich erst in Kapitel 3. Die Wiederverwendung und die Wartbarkeit sind miteinander verwoben. Ich will Ihnen diese Features anhand eines Beispiels erläutern: Bei der Programmierung ist es manchmal notwendig, dass eine gewisse Basisfunktionalität, die in einem Programm (oder Programmteil) verwendet wird, in einem anderen Programm in einer erweiterten Form zur Verfügung stehen muss. Die Basisfunktionalität darf dabei allerdings nicht verändert werden, damit beide Programme zuverlässig laufen. Vererbung und Polymorphismus 26

30 Das folgende Beispiel verdeutlicht diesen wichtigen Punkt: Eine Klasse soll eine serielle Schnittstelle des Computers repräsentieren und die Kommunikation über diese mit irgendwelchen angeschlossenen Geräten vereinfachen. Diese Klasse sollte einige Eigenschaften zur Einstellung der Parameter der seriellen Schnittstelle besitzen. Das wären zum Beispiel Eigenschaften wie ComPort, Baudrate, Parity und Handshake (die Bedeutung dieser Parameter ist an dieser Stelle nicht wichtig). Eine Methode Open öffnet die serielle Schnittstelle mit den angegebenen Parametern, eine Methode Send erledigt das Senden von Zeichenketten. Eine Methode Read liest empfangene Zeichen aus dem Puffer der seriellen Schnittstelle und gibt diese zurück. Ich nenne diese Klasse Comm. Diese Klasse berücksichtigt beim Senden und Empfangen von Daten kein besonderes Protokoll 1, Daten werden einfach Zeichen für Zeichen gesendet und empfangen. Irgendwann ist die Klasse fertig gestellt, getestet und funktioniert (hoffentlich) einwandfrei. // Klasse zur einfachen seriellen Kommunikation class Comm int ComPort; int Baudrate; int Handshake; char Parity; ; bool Open() // für das Beispiel nicht implementiert return true; bool Send(string data) // für das Beispiel nicht implementiert cout << "Sende Daten: " << data << endl; return true; string Read() // für das Beispiel nicht implementiert void Close() // für das Beispiel nicht implementiert // Die Programmierung der Methoden ist nicht Bestandteil // dieses Beispiels In einem Programm, das irgendwann später entwickelt wird, soll eine Kommunikation über die serielle Schnittstelle mit einem externen Gerät programmiert werden, das Daten nach einem DIN- Protokoll sendet und empfängt. Bei einem solchen Protokoll werden die Daten u. a. mit einer Checksumme versehen, die beim Empfang dazu verwendet wird, zu überprüfen, ob die Daten korrekt empfangen wurden. Der Programmierer würde sich jetzt sehr viel Arbeit machen, wenn er das, was in der Comm-Klasse bereits fertig programmiert ist, nicht wiederverwenden würde. Er schreibt also einfach eine neue Klasse, die von der Comm-Klasse abgeleitet wird und die damit alle Eigenschaften und Methoden erbt. Um die neue Funktionalität zu programmieren, muss er lediglich 1 Ein Protokoll beschreibt (im Computer), wie Daten gesendet und empfangen werden. Einfache Protokolle versehen die gesendeten Daten mit einer so genannten Checksumme, die aus den Daten errechnet und an diese hinten angehängt wird. Mit Hilfe dieser Checksumme kann der Empfänger überprüfen, ob die Daten korrekt gesendet wurden. Komplexere Protokolle, wie TCP/IP, trennen die gesendeten Daten zusätzlich noch in kleine Pakete auf, die jedes für sich mit einer Checksumme und einer Paketnummer versehen werden. Vererbung und Polymorphismus 27

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung Vorkurs C++ Programmierung Klassen Letzte Stunde Speicherverwaltung automatische Speicherverwaltung auf dem Stack dynamische Speicherverwaltung auf dem Heap new/new[] und delete/delete[] Speicherklassen:

Mehr

Zählen von Objekten einer bestimmten Klasse

Zählen von Objekten einer bestimmten Klasse Zählen von Objekten einer bestimmten Klasse Ziel, Inhalt Zur Übung versuchen wir eine Klasse zu schreiben, mit der es möglich ist Objekte einer bestimmten Klasse zu zählen. Wir werden den ++ und den --

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung 1 Geschichte Dahl, Nygaard: Simula 67 (Algol 60 + Objektorientierung) Kay et al.: Smalltalk (erste rein-objektorientierte Sprache) Object Pascal, Objective C, C++ (wiederum

Mehr

Einführung in die Java- Programmierung

Einführung in die Java- Programmierung Einführung in die Java- Programmierung Dr. Volker Riediger Tassilo Horn riediger horn@uni-koblenz.de WiSe 2012/13 1 Wichtig... Mittags keine Pommes... Praktikum A 230 C 207 (Madeleine + Esma) F 112 F 113

Mehr

Einführung in die Programmierung

Einführung in die Programmierung Technische Universität München WS 2003/2004 Institut für Informatik Prof. Dr. Christoph Zenger Testklausur Einführung in die Programmierung Probeklausur Java (Lösungsvorschlag) 1 Die Klasse ArrayList In

Mehr

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

Unterprogramme. Funktionen. Bedeutung von Funktionen in C++ Definition einer Funktion. Definition einer Prozedur Unterprogramme Unterprogramme sind abgekapselte Programmfragmente, welche es erlauben, bestimmte Aufgaben in wiederverwendbarer Art umzusetzen. Man unterscheidet zwischen Unterprogrammen mit Rückgabewert

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

1 Vom Problem zum Programm

1 Vom Problem zum Programm Hintergrundinformationen zur Vorlesung GRUNDLAGEN DER INFORMATIK I Studiengang Elektrotechnik WS 02/03 AG Betriebssysteme FB3 Kirsten Berkenkötter 1 Vom Problem zum Programm Aufgabenstellung analysieren

Mehr

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektorientierte Programmierung für Anfänger am Beispiel PHP Objektorientierte Programmierung für Anfänger am Beispiel PHP Johannes Mittendorfer http://jmittendorfer.hostingsociety.com 19. August 2012 Abstract Dieses Dokument soll die Vorteile der objektorientierten

Mehr

5 DATEN. 5.1. Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

5 DATEN. 5.1. Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu Daten Makro + VBA effektiv 5 DATEN 5.1. Variablen Variablen können beliebige Werte zugewiesen und im Gegensatz zu Konstanten jederzeit im Programm verändert werden. Als Variablen können beliebige Zeichenketten

Mehr

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf http://informatik.swoke.de. Seite 1 von 22 Kapitel 19 Vererbung, UML Seite 1 von 22 Vererbung - Neben der Datenabstraktion und der Datenkapselung ist die Vererbung ein weiteres Merkmal der OOP. - Durch Vererbung werden die Methoden und die Eigenschaften

Mehr

Vererbung & Schnittstellen in C#

Vererbung & Schnittstellen in C# Vererbung & Schnittstellen in C# Inhaltsübersicht - Vorüberlegung - Vererbung - Schnittstellenklassen - Zusammenfassung 1 Vorüberlegung Wozu benötigt man Vererbung überhaubt? 1.Um Zeit zu sparen! Verwendung

Mehr

Klassenbeziehungen & Vererbung

Klassenbeziehungen & Vererbung Klassenbeziehungen & Vererbung VL Objektorientierte Programmierung Raimund Kirner teilweise nach Folien von Franz Puntigam, TU Wien Überblick Arten von Klassenbeziehungen Untertypen versus Vererbung in

Mehr

Einführung in die Programmierung

Einführung in die Programmierung : Inhalt Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund - mit / ohne Parameter - mit / ohne Rückgabewerte

Mehr

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

Java Kurs für Anfänger Einheit 4 Klassen und Objekte Java Kurs für Anfänger Einheit 4 Klassen und Ludwig-Maximilians-Universität München (Institut für Informatik: Programmierung und Softwaretechnik von Prof.Wirsing) 13. Juni 2009 Inhaltsverzeichnis klasse

Mehr

Zwischenablage (Bilder, Texte,...)

Zwischenablage (Bilder, Texte,...) Zwischenablage was ist das? Informationen über. die Bedeutung der Windows-Zwischenablage Kopieren und Einfügen mit der Zwischenablage Vermeiden von Fehlern beim Arbeiten mit der Zwischenablage Bei diesen

Mehr

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff Programmieren in C Macros, Funktionen und modulare Programmstruktur Prof. Dr. Nikolaus Wulff Der C Präprozessor Vor einem Compile Lauf werden alle Präprozessor Kommandos/Makros ausgewertet. Diese sind

Mehr

Computeranwendung und Programmierung (CuP)

Computeranwendung und Programmierung (CuP) Computeranwendung und Programmierung (CuP) VO: Peter Auer (Informationstechnologie) UE: Norbert Seifter (Angewandet Mathematik) Organisatorisches (Vorlesung) Vorlesungszeiten Montag 11:15 12:45 Freitag

Mehr

13 OOP MIT DELPHI. Records und Klassen Ein Vergleich

13 OOP MIT DELPHI. Records und Klassen Ein Vergleich 13 OOP MIT DELPHI Delphi war früher "Object Pascal". Dieser Name impliziert eine Funktionalität, welche in der Welt der Programmierung nicht mehr wegzudenken ist: die objektorientierte Programmierung,

Mehr

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang sysplus.ch outlook - mail-grundlagen Seite 1/8 Outlook Mail-Grundlagen Posteingang Es gibt verschiedene Möglichkeiten, um zum Posteingang zu gelangen. Man kann links im Outlook-Fenster auf die Schaltfläche

Mehr

CMS.R. Bedienungsanleitung. Modul Cron. Copyright 10.09.2009. www.sruttloff.de CMS.R. - 1 - Revision 1

CMS.R. Bedienungsanleitung. Modul Cron. Copyright 10.09.2009. www.sruttloff.de CMS.R. - 1 - Revision 1 CMS.R. Bedienungsanleitung Modul Cron Revision 1 Copyright 10.09.2009 www.sruttloff.de CMS.R. - 1 - WOZU CRON...3 VERWENDUNG...3 EINSTELLUNGEN...5 TASK ERSTELLEN / BEARBEITEN...6 RECHTE...7 EREIGNISSE...7

Mehr

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet C++ Grundlagen ++ bedeutet Erweiterung zum Ansi C Standard Hier wird eine Funktion eingeleitet Aufbau: In dieser Datei stehen die Befehle, die gestartet werden, wenn das Programm gestartet wird Int main()

Mehr

Folge 18 - Vererbung

Folge 18 - Vererbung Workshop Folge 18 - Vererbung 18.1 Ein einfacher Fall der Vererbung Schritt 1 - Vorbereitungen Besorgen Sie sich - vielleicht aus einer der Übungen der Folge 17 - ein fertiges und lauffähiges Listenprojekt,

Mehr

Dokumentation IBIS Monitor

Dokumentation IBIS Monitor Dokumentation IBIS Monitor Seite 1 von 16 11.01.06 Inhaltsverzeichnis 1. Allgemein 2. Installation und Programm starten 3. Programmkonfiguration 4. Aufzeichnung 4.1 Aufzeichnung mitschneiden 4.1.1 Inhalt

Mehr

Anleitung über den Umgang mit Schildern

Anleitung über den Umgang mit Schildern Anleitung über den Umgang mit Schildern -Vorwort -Wo bekommt man Schilder? -Wo und wie speichert man die Schilder? -Wie füge ich die Schilder in meinen Track ein? -Welche Bauteile kann man noch für Schilder

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

Objektorientierte Programmierung mit C++ Vector und List

Objektorientierte Programmierung mit C++ Vector und List Vector und List Ziel, Inhalt Wir lernen die Klassen vector und list aus der Standard-C++ Library kennen und anwenden. In einer Übung wenden wir diese Klassen an um einen Medienshop (CD s und Bücher) zu

Mehr

Enigmail Konfiguration

Enigmail Konfiguration Enigmail Konfiguration 11.06.2006 Steffen.Teubner@Arcor.de Enigmail ist in der Grundkonfiguration so eingestellt, dass alles funktioniert ohne weitere Einstellungen vornehmen zu müssen. Für alle, die es

Mehr

Modellierung und Programmierung 1

Modellierung und Programmierung 1 Modellierung und Programmierung 1 Prof. Dr. Sonja Prohaska Computational EvoDevo Group Institut für Informatik Universität Leipzig 19. November 2015 Gültigkeitsbereich (Scope) von Variablen { int m; {

Mehr

M. Graefenhan 2000-12-07. Übungen zu C. Blatt 3. Musterlösung

M. Graefenhan 2000-12-07. Übungen zu C. Blatt 3. Musterlösung M. Graefenhan 2000-12-07 Aufgabe Lösungsweg Übungen zu C Blatt 3 Musterlösung Schreiben Sie ein Programm, das die Häufigkeit von Zeichen in einem eingelesenen String feststellt. Benutzen Sie dazu ein zweidimensionales

Mehr

Arbeiten mit UMLed und Delphi

Arbeiten mit UMLed und Delphi Arbeiten mit UMLed und Delphi Diese Anleitung soll zeigen, wie man Klassen mit dem UML ( Unified Modeling Language ) Editor UMLed erstellt, in Delphi exportiert und dort so einbindet, dass diese (bis auf

Mehr

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren Lineargleichungssysteme: Additions-/ Subtraktionsverfahren W. Kippels 22. Februar 2014 Inhaltsverzeichnis 1 Einleitung 2 2 Lineargleichungssysteme zweiten Grades 2 3 Lineargleichungssysteme höheren als

Mehr

Datensicherung. Beschreibung der Datensicherung

Datensicherung. Beschreibung der Datensicherung Datensicherung Mit dem Datensicherungsprogramm können Sie Ihre persönlichen Daten problemlos Sichern. Es ist möglich eine komplette Datensicherung durchzuführen, aber auch nur die neuen und geänderten

Mehr

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss Systeme 1 Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss Threads Die Adressräume verschiedener Prozesse sind getrennt und geschützt gegen den Zugriff anderer Prozesse. Threads sind leichtgewichtige

Mehr

Objektbasierte Entwicklung

Objektbasierte Entwicklung Embedded Software Objektbasierte Entwicklung Objektorientierung in C? Prof. Dr. Nikolaus Wulff Objektbasiert entwickeln Ohne C++ wird meist C im alten Stil programmiert. => Ein endlose while-schleife mit

Mehr

4. BEZIEHUNGEN ZWISCHEN TABELLEN

4. BEZIEHUNGEN ZWISCHEN TABELLEN 4. BEZIEHUNGEN ZWISCHEN TABELLEN Zwischen Tabellen können in MS Access Beziehungen bestehen. Durch das Verwenden von Tabellen, die zueinander in Beziehung stehen, können Sie Folgendes erreichen: Die Größe

Mehr

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen Binäre Bäume 1. Allgemeines Binäre Bäume werden grundsätzlich verwendet, um Zahlen der Größe nach, oder Wörter dem Alphabet nach zu sortieren. Dem einfacheren Verständnis zu Liebe werde ich mich hier besonders

Mehr

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten Berichte bieten die gleichen Möglichkeit zur Berechnung von Werten wie Formulare und noch einige mehr. Im Gegensatz zu Formularen bieten Berichte die Möglichkeit, eine laufende Summe zu bilden oder Berechnungen

Mehr

Klausur in Programmieren

Klausur in Programmieren Studiengang Sensorik/Sensorsystemtechnik Note / normierte Punkte Klausur in Programmieren Wintersemester 2010/11, 17. Februar 2011 Dauer: 1,5h Hilfsmittel: Keine (Wörterbücher sind auf Nachfrage erlaubt)

Mehr

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 von Markus Mack Stand: Samstag, 17. April 2004 Inhaltsverzeichnis 1. Systemvorraussetzungen...3 2. Installation und Start...3 3. Anpassen der Tabelle...3

Mehr

Testen mit JUnit. Motivation

Testen mit JUnit. Motivation Test First Design for Test in Eclipse (eigentlich: ) zu einer Klasse Beispiel zur Demonstration Ergänzungen Test First "Immer dann, wenn Du in Versuchung kommst, etwas wie eine print- Anweisung oder einen

Mehr

Praktikum Ingenieurinformatik. Termin 2. Verzweigungen (if-else), printf und scanf, while-schleife

Praktikum Ingenieurinformatik. Termin 2. Verzweigungen (if-else), printf und scanf, while-schleife Praktikum Ingenieurinformatik Termin 2 Verzweigungen (if-else), printf und scanf, while-schleife 1 1. Import/Export von Eclipse-Projekten 2. Verzweigungen (if-else-anweisung) 3. printf und scanf 4. Übungsaufgaben

Mehr

Tutorial. Bibliothek AutoGUITest V1.0. Windows-Benutzeroberflächen automatisiert testen. Ausgabe: 6.6.02. 06.06.02 / 13:51 Seite 1

Tutorial. Bibliothek AutoGUITest V1.0. Windows-Benutzeroberflächen automatisiert testen. Ausgabe: 6.6.02. 06.06.02 / 13:51 Seite 1 Bibliothek AutoGUITest V1.0 Windows-Benutzeroberflächen automatisiert testen Tutorial Ausgabe: 6.6.02 06.06.02 / 13:51 Seite 1 Inhalt 1 Übersicht...3 2 Funktionsweise...3 3 Funktionsumfang...3 4 Einsatz

Mehr

Wie halte ich Ordnung auf meiner Festplatte?

Wie halte ich Ordnung auf meiner Festplatte? Wie halte ich Ordnung auf meiner Festplatte? Was hältst du von folgender Ordnung? Du hast zu Hause einen Schrank. Alles was dir im Wege ist, Zeitungen, Briefe, schmutzige Wäsche, Essensreste, Küchenabfälle,

Mehr

Deklarationen in C. Prof. Dr. Margarita Esponda

Deklarationen in C. Prof. Dr. Margarita Esponda Deklarationen in C 1 Deklarationen Deklarationen spielen eine zentrale Rolle in der C-Programmiersprache. Deklarationen Variablen Funktionen Die Deklarationen von Variablen und Funktionen haben viele Gemeinsamkeiten.

Mehr

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

2. Semester, 2. Prüfung, Lösung 2. Semester, 2. Prüfung, Lösung Name Die gesamte Prüfung bezieht sich auf die Programmierung in C++! Prüfungsdauer: 90 Minuten Mit Kugelschreiber oder Tinte schreiben Lösungen können direkt auf die Aufgabenblätter

Mehr

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005 Einführung in die objektorientierte Programmierung mit Java Klausur am 19. Oktober 2005 Matrikelnummer: Nachname: Vorname: Semesteranzahl: Die Klausur besteht aus drei Frageblöcken zu den Inhalten der

Mehr

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine PhotoLine S/W mit PhotoLine Erstellt mit Version 16.11 Ich liebe Schwarzweiß-Bilder und schaue mir neidisch die Meisterwerke an, die andere Fotografen zustande bringen. Schon lange versuche ich, auch so

Mehr

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 Referentin: Dr. Kelly Neudorfer Universität Hohenheim Was wir jetzt besprechen werden ist eine Frage, mit denen viele

Mehr

CodeSaver. Vorwort. Seite 1 von 6

CodeSaver. Vorwort. Seite 1 von 6 CodeSaver Vorwort Die Flut der Passwörter nimmt immer mehr zu. Kontopasswörter, Passwörter für Homepages, Shellzugriffe, Registrierungscodes für Programme und und und. Da ich aber nicht sonderlich viel

Mehr

Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten

Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten Stundenerfassung Version 1.8 Anleitung Arbeiten mit Replikaten 2008 netcadservice GmbH netcadservice GmbH Augustinerstraße 3 D-83395 Freilassing Dieses Programm ist urheberrechtlich geschützt. Eine Weitergabe

Mehr

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2015/2016 Wirtschaftsingenieur Bachelor 5. Aufgabe Datenstruktur, Dateieingabe und -ausgabe

Hochschule Darmstadt Informatik-Praktikum (INF 1) WS 2015/2016 Wirtschaftsingenieur Bachelor 5. Aufgabe Datenstruktur, Dateieingabe und -ausgabe Aufgabenstellung Für eine Hausverwaltung sollen für maximal 500 Wohnungen Informationen gespeichert werden, die alle nach der gleichen Weise wie folgt strukturiert sind: Art Baujahr Wohnung Whnginfo Nebenkosten

Mehr

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: VBA Programmierung mit Excel Schleifen 1/6 Erweiterung der Aufgabe Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: Es müssen also 11 (B L) x 35 = 385 Zellen berücksichtigt

Mehr

Java: Vererbung. Teil 3: super() www.informatikzentrale.de

Java: Vererbung. Teil 3: super() www.informatikzentrale.de Java: Vererbung Teil 3: super() Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und IMMER zuerst den Konstruktor der Elternklasse auf! Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und

Mehr

192.168.0.1. Wenn wir also versuchen auf einen anderen PC zuzugreifen, dann können wir sowohl per Name als auch mit der Adresse suchen.

192.168.0.1. Wenn wir also versuchen auf einen anderen PC zuzugreifen, dann können wir sowohl per Name als auch mit der Adresse suchen. Windows Netzwerk Sie haben einen oder mehrere PC mit einander verbunden? Dann sollte man das auch nutzen. Generelles: Ein PC hat in der Regel IMMER eine feste Nummer / Adresse (egal ob wechselnd oder immer

Mehr

4 Aufzählungen und Listen erstellen

4 Aufzählungen und Listen erstellen 4 4 Aufzählungen und Listen erstellen Beim Strukturieren von Dokumenten und Inhalten stellen Listen und Aufzählungen wichtige Werkzeuge dar. Mit ihnen lässt sich so ziemlich alles sortieren, was auf einer

Mehr

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6 Gudrun Fischer Sascha Kriewel programmierung@is.informatik.uni-duisburg.de Anmeldung zur Klausur! Übungsblatt Nr. 6 Um an der Klausur teilzunehmen, müssen sich Studierende der angewandten Informatik in

Mehr

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

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

Mehr

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster Es gibt in Excel unter anderem die so genannten Suchfunktionen / Matrixfunktionen Damit können Sie Werte innerhalb eines bestimmten Bereichs suchen. Als Beispiel möchte ich die Funktion Sverweis zeigen.

Mehr

GITS Steckbriefe 1.9 - Tutorial

GITS Steckbriefe 1.9 - Tutorial Allgemeines Die Steckbriefkomponente basiert auf der CONTACTS XTD Komponente von Kurt Banfi, welche erheblich modifiziert bzw. angepasst wurde. Zuerst war nur eine kleine Änderung der Komponente für ein

Mehr

Mediator 9 - Lernprogramm

Mediator 9 - Lernprogramm Mediator 9 - Lernprogramm Ein Lernprogramm mit Mediator erstellen Mediator 9 bietet viele Möglichkeiten, CBT-Module (Computer Based Training = Computerunterstütztes Lernen) zu erstellen, z. B. Drag & Drop

Mehr

ecaros2 - Accountmanager

ecaros2 - Accountmanager ecaros2 - Accountmanager procar informatik AG 1 Stand: FS 09/2012 Inhaltsverzeichnis 1 Aufruf des ecaros2-accountmanager...3 2 Bedienung Accountmanager...4 procar informatik AG 2 Stand: FS 09/2012 1 Aufruf

Mehr

14.4.2016. Technische Hochschule Georg Agricola WORKSHOP TEIL 3. IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt

14.4.2016. Technische Hochschule Georg Agricola WORKSHOP TEIL 3. IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt 14.4.2016 Technische Hochschule Georg Agricola WORKSHOP TEIL 3 IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt Inhaltsverzeichnis 1. Kurzfassung zur Projekterstellung... 2 2. Morse-Tabelle...

Mehr

Kennen, können, beherrschen lernen was gebraucht wird www.doelle-web.de

Kennen, können, beherrschen lernen was gebraucht wird www.doelle-web.de Inhaltsverzeichnis Inhaltsverzeichnis... 1 Grundlagen... 2 Hyperlinks innerhalb einer Datei... 2 Verweisziel definieren... 2 Einen Querverweis setzen... 3 Verschiedene Arten von Hyperlinks... 3 Einfache

Mehr

Primzahlen und RSA-Verschlüsselung

Primzahlen und RSA-Verschlüsselung Primzahlen und RSA-Verschlüsselung Michael Fütterer und Jonathan Zachhuber 1 Einiges zu Primzahlen Ein paar Definitionen: Wir bezeichnen mit Z die Menge der positiven und negativen ganzen Zahlen, also

Mehr

Einführung in Javadoc

Einführung in Javadoc Einführung in Javadoc Johannes Rinn http://java.sun.com/j2se/javadoc Was ist Javadoc? Javadoc ist ein Werkzeug, dass eine standardisierte Dokumentation für die Programmiersprache Java unterstützt. Vorteil:

Mehr

Aufklappelemente anlegen

Aufklappelemente anlegen Aufklappelemente anlegen Dieses Dokument beschreibt die grundsätzliche Erstellung der Aufklappelemente in der mittleren und rechten Spalte. Login Melden Sie sich an der jeweiligen Website an, in dem Sie

Mehr

Software Engineering Klassendiagramme Assoziationen

Software Engineering Klassendiagramme Assoziationen Software Engineering Klassendiagramme Assoziationen Prof. Adrian A. Müller, PMP, PSM 1, CSM Fachbereich Informatik und Mikrosystemtechnik 1 Lesen von Multiplizitäten (1) Multiplizitäten werden folgendermaßen

Mehr

Die Programmiersprache C99: Zusammenfassung

Die Programmiersprache C99: Zusammenfassung Die Programmiersprache C99: Zusammenfassung Jörn Loviscach Versionsstand: 7. Dezember 2010, 19:30 Die nummerierten Felder sind absichtlich leer, zum Ausfüllen in der Vorlesung. Videos dazu: http://www.youtube.com/joernloviscach

Mehr

Jederzeit Ordnung halten

Jederzeit Ordnung halten Kapitel Jederzeit Ordnung halten 6 auf Ihrem Mac In diesem Buch war bereits einige Male vom Finder die Rede. Dieses Kapitel wird sich nun ausführlich diesem so wichtigen Programm widmen. Sie werden das

Mehr

Wir arbeiten mit Zufallszahlen

Wir arbeiten mit Zufallszahlen Abb. 1: Bei Kartenspielen müssen zu Beginn die Karten zufällig ausgeteilt werden. Wir arbeiten mit Zufallszahlen Jedesmal wenn ein neues Patience-Spiel gestartet wird, muss das Computerprogramm die Karten

Mehr

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek Programmieren I Dr. Klaus Höppner Hochschule Darmstadt Wintersemester 2008/2009 1 / 22 2 / 22 Strategie zum Entwurf von Klassen Beispiele Objektorientierte Sichtweise: Mit welchen Objekten habe ich es

Mehr

teamsync Kurzanleitung

teamsync Kurzanleitung 1 teamsync Kurzanleitung Version 4.0-19. November 2012 2 1 Einleitung Mit teamsync können Sie die Produkte teamspace und projectfacts mit Microsoft Outlook synchronisieren.laden Sie sich teamsync hier

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Programmierkurs C++ Kapitel 7:Objektorientierte Programmierung Seite 1 Objektorientierte Programmierung If programming in PASCAL is like put in a straightjacket, then programming in C is like playing with

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Konstruktor, Statische Methoden Packages Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/fischer Initialisierung von Datenstrukturen

Mehr

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b AGROPLUS Buchhaltung Daten-Server und Sicherheitskopie Version vom 21.10.2013b 3a) Der Daten-Server Modus und der Tresor Der Daten-Server ist eine Betriebsart welche dem Nutzer eine grosse Flexibilität

Mehr

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1 Kapitel 4 Die Datenbank Kuchenbestellung Seite 1 4 Die Datenbank Kuchenbestellung In diesem Kapitel werde ich die Theorie aus Kapitel 2 Die Datenbank Buchausleihe an Hand einer weiteren Datenbank Kuchenbestellung

Mehr

Menü Macro. WinIBW2-Macros unter Windows7? Macros aufnehmen

Menü Macro. WinIBW2-Macros unter Windows7? Macros aufnehmen Menü Macro WinIBW2-Macros unter Windows7?... 1 Macros aufnehmen... 1 Menübefehle und Schaltflächen in Macros verwenden... 4 Macros bearbeiten... 4 Macros löschen... 5 Macro-Dateien... 5 Macros importieren...

Mehr

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

Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Gute Lösung: Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Der Sourcecode wird an den entsprechenden Stellen im Programm wiederholt Programm wird lang

Mehr

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

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {... PIWIN I Kap. 8 Objektorientierte Programmierung - Vererbung 31 Schlüsselwort: final Verhindert, dass eine Methode überschrieben wird public final int holekontostand() {... Erben von einer Klasse verbieten:

Mehr

Zahlen auf einen Blick

Zahlen auf einen Blick Zahlen auf einen Blick Nicht ohne Grund heißt es: Ein Bild sagt mehr als 1000 Worte. Die meisten Menschen nehmen Informationen schneller auf und behalten diese eher, wenn sie als Schaubild dargeboten werden.

Mehr

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 9 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

Mehr

Viele Bilder auf der FA-Homepage

Viele Bilder auf der FA-Homepage Viele Bilder auf der FA-Homepage Standardmäßig lassen sich auf einer FA-Homepage nur 2 Bilder mit zugehörigem Text unterbringen. Sollen es mehr Bilder sein, muss man diese als von einer im Internet

Mehr

Programmierung in C. Grundlagen. Stefan Kallerhoff

Programmierung in C. Grundlagen. Stefan Kallerhoff Programmierung in C Grundlagen Stefan Kallerhoff Vorstellungsrunde Name Hobby/Beruf Schon mal was programmiert? Erwartungen an den Kurs Lieblingstier Für zu Hause C-Buch online: http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/

Mehr

5.5.8 Öffentliche und private Eigenschaften

5.5.8 Öffentliche und private Eigenschaften 5.5.8 Öffentliche und private Eigenschaften Schnittstellen vs. Implementierungen: Schnittstelle einer Klasse beschreibt, was eine Klasse leistet und wie sie benutzt werden kann, ohne dass ihre Implementierung

Mehr

Abwesenheitsnotiz im Exchange Server 2010

Abwesenheitsnotiz im Exchange Server 2010 Abwesenheitsnotiz im Exchange Server 2010 1.) Richten Sie die Abwesenheitsnotiz in Outlook 2010 ein und definieren Sie, an welche Absender diese gesendet werden soll. Klicken Sie dazu auf Datei -> Informationen

Mehr

Dokumentenverwaltung im Internet

Dokumentenverwaltung im Internet Dokumentenverwaltung im Internet WS 09/10 mit: Thema: Workflow und Rollenverteilung im Backend Gruppe: DVI 10 Patrick Plaum und Kay Hofmann Inhalt 1. Benutzer und Benutzergruppen erstellen...2 1.1. Benutzergruppen...2

Mehr

Stepperfocuser 2.0 mit Bootloader

Stepperfocuser 2.0 mit Bootloader Stepperfocuser 2.0 mit Bootloader Info Für den Stepperfocuser 2.0 gibt es einen Bootloader. Dieser ermöglicht es, die Firmware zu aktualisieren ohne dass man ein spezielles Programmiergerät benötigt. Die

Mehr

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java: Technische Informatik für Ingenieure (TIfI) WS 2005/2006, Vorlesung 9 II. Grundlagen der Programmierung Ekkart Kindler Funktionen und Prozeduren Datenstrukturen 9. Datenstrukturen Daten zusammenfassen

Mehr

Einführung in die C++ Programmierung für Ingenieure

Einführung in die C++ Programmierung für Ingenieure Einführung in die C++ Programmierung für Ingenieure MATTHIAS WALTER / JENS KLUNKER Universität Rostock, Lehrstuhl für Modellierung und Simulation 14. November 2012 c 2012 UNIVERSITÄT ROSTOCK FACULTY OF

Mehr

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung Anleitung zur Daten zur Datensicherung und Datenrücksicherung Datensicherung Es gibt drei Möglichkeiten der Datensicherung. Zwei davon sind in Ges eingebaut, die dritte ist eine manuelle Möglichkeit. In

Mehr

Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert

Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert Beamen in EEP Das sogenannte Beamen ist auch in EEP möglich ohne das Zusatzprogramm Beamer. Zwar etwas umständlicher aber es funktioniert Zuerst musst du dir 2 Programme besorgen und zwar: Albert, das

Mehr

Der neue persönliche Bereich/die CommSy-Leiste

Der neue persönliche Bereich/die CommSy-Leiste Der neue persönliche Bereich/die CommSy-Leiste Mit der neue CommSy-Version wurde auch der persönliche Bereich umstrukturiert. Sie finden all Ihre persönlichen Dokumente jetzt in Ihrer CommSy-Leiste. Ein

Mehr

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala

Das Typsystem von Scala. L. Piepmeyer: Funktionale Programmierung - Das Typsystem von Scala Das Typsystem von Scala 1 Eigenschaften Das Typsystem von Scala ist statisch, implizit und sicher 2 Nichts Primitives Alles ist ein Objekt, es gibt keine primitiven Datentypen scala> 42.hashCode() res0:

Mehr

Hilfedatei der Oden$-Börse Stand Juni 2014

Hilfedatei der Oden$-Börse Stand Juni 2014 Hilfedatei der Oden$-Börse Stand Juni 2014 Inhalt 1. Einleitung... 2 2. Die Anmeldung... 2 2.1 Die Erstregistrierung... 3 2.2 Die Mitgliedsnummer anfordern... 4 3. Die Funktionen für Nutzer... 5 3.1 Arbeiten

Mehr

1 topologisches Sortieren

1 topologisches Sortieren Wolfgang Hönig / Andreas Ecke WS 09/0 topologisches Sortieren. Überblick. Solange noch Knoten vorhanden: a) Suche Knoten v, zu dem keine Kante führt (Falls nicht vorhanden keine topologische Sortierung

Mehr

Professionelle Seminare im Bereich MS-Office

Professionelle Seminare im Bereich MS-Office Serienbrief aus Outlook heraus Schritt 1 Zuerst sollten Sie die Kontakte einblenden, damit Ihnen der Seriendruck zur Verfügung steht. Schritt 2 Danach wählen Sie bitte Gerhard Grünholz 1 Schritt 3 Es öffnet

Mehr

Access 2010. Grundlagen für Anwender. Andrea Weikert 1. Ausgabe, 1. Aktualisierung, Juli 2012. inkl. zusätzlichem Übungsanhang ACC2010-UA

Access 2010. Grundlagen für Anwender. Andrea Weikert 1. Ausgabe, 1. Aktualisierung, Juli 2012. inkl. zusätzlichem Übungsanhang ACC2010-UA Andrea Weikert 1. Ausgabe, 1. Aktualisierung, Juli 2012 Access 2010 Grundlagen für Anwender inkl. zusätzlichem Übungsanhang ACC2010-UA 3 Access 2010 - Grundlagen für Anwender 3 Daten in Formularen bearbeiten

Mehr

Einführung in die Programmierung (EPR)

Einführung in die Programmierung (EPR) Goethe-Center for Scientific Computing (G-CSC) Goethe-Universität Frankfurt am Main Einführung in die Programmierung (EPR) (Übung, Wintersemester 2014/2015) Dr. S. Reiter, M. Rupp, Dr. A. Vogel, Dr. K.

Mehr

Erfolgsmeldungen im Praxisbetrieb

Erfolgsmeldungen im Praxisbetrieb Inhalt 1. Was ist KV-Connect... 1 a. KV-SafeNet... 1 b. KV-Connect... 1 2. Vorbereitung der Installation... 2 a. KV-Connect-Zugangsdaten... 2 3. Einrichtung von KV-Connect... 3 a. Einstellungen im Programm...

Mehr