SlideShare ist ein Scribd-Unternehmen logo
1 von 16
Kurs: Objektorientiertes Programmieren mit C++ (http://tutego.de/g/CPP1)
Autor: Boris Schäling

Kapitel 1: Klassen und Objekte
Inhaltsverzeichnis

   •   1.1 Allgemeines
   •   1.2 Überblick
   •   1.3 Klassen entwickeln
   •   1.4 Objekte anlegen
   •   1.5 Zugriffsrechte
   •   1.6 Praxis-Beispiel

1.1 Allgemeines. Konzepte und praktische Umsetzung
In der objektorientierten Programmierung wird mit Begriffen wie Klassen, Objekten,
Instanzen, Vererbung, Kapselung und so weiter nur so um sich geschmissen. In diesem
Kapitel erhalten Sie einen Überblick über die einzelnen Bestandteile der Objektorientierung,
wie diese zusammenhängen und vor allem welchen Sinn sie haben. Diese Übersicht gilt
hierbei nicht nur für die Programmiersprache C++, sondern grundsätzlich auch für andere
objektorientierte Sprachen.

Nach dem Rundflug über die Objektorientierung werden Sie in die notwendige Syntax und
Semantik eingewiesen, um einfache Klassen in C++ selbst zu erstellen.

1.2 Überblick. Objektorientierte Programmierung
Um die objektorientierte Programmierung herrscht - vor allem bei Entwicklern, die nicht
objektorientiert programmieren - ein Riesenhype. Die Objektorientierung scheint das Non-
Plus-Ultra, der heilige Gral unter den Programmiersprachen zu sein. Objektorientiert-
entwickelte Programme scheinen grundsätzlich besser als Anwendungen zu sein, die in einer
nicht-objektorientierten Programmiersprache entwickelt sind. Woher kommt dieser Hype
um die Objektorientierung?

Bei der Objektorientierung stehen, wie der Name schon sagt, Objekte im Vordergrund. Ein
Programm wird nicht mehr als eine Art Wasserfall betrachtet, in dem Informationen von
oben nach unten fließen. Dieses Flusskonzept von Daten spielt in der Objektorientierung
keine Rolle.

Wird eine Aufgabenstellung objektorientiert gelöst, werden zuerst Objekte, die zur Lösung
der Aufgabe miteinander agieren müssen, herausgearbeitet. Um objektorientiert
programmieren zu können muss erstmal klar sein, was für Objekte eigentlich genau benötigt
werden. Dies hängt natürlich von der Aufgabe ab. Soll beispielsweise eine Software für einen
Bankautomaten zum Geldabheben objektorientiert entwickelt werden, könnten sich als
notwendige Objekte zur Lösung der Aufgabe Kunde und Bank erweisen. Das Abheben von
Geld ist schließlich ein Vorgang, bei dem ein Kunde Daten in einen Bankautomaten eingibt
und elektronisch mit einer Bank kommuniziert.

Eine objektorientierte Programmiersprache macht es nun möglich, den Kunden und die Bank
hinüber in die Software zu nehmen. Das heißt, in einer objektorientierten
Programmiersprache werden die Objekte, die herausgearbeitet wurden, direkt in den Code
übernommen und dort nachgebildet. Dieses Nachbilden sieht derart aus, dass für die Lösung
des Problems benötigte Eigenschaften und Fähigkeiten der Objekte in den Code
übernommen werden.

Zum Beispiel spielt für die Entwicklung der Bankautomatensoftware die Haarfarbe des
Kunden keine Rolle. Ob er jedoch die PIN für sein Bankkonto kennt, ist wichtig. Daher könnte
dem Objekt Kunde eine Eigenschaft PIN gegeben werden. Eine Eigenschaft Haarfarbe wäre
unsinnig.

Um die PIN vom Kunden zu erfahren, muss er sie dem Bankautomaten mitteilen. Der Kunde
muss die Fähigkeit besitzen, eine PIN eingeben zu können. Diese Fähigkeit würde also dem
entsprechenden Objekt Kunde in der Objektorientierung gegeben werden. Dass der Kunde
außerdem beispielsweise tanzen kann, interessiert in diesem Zusammenhang nicht. Eine
derartige Fähigkeit wird zum Geldabheben am Bankautomaten nicht benötigt.

Als objektorientierter Entwickler müssen Sie also für die Aufgabenstellung relevante Objekte
identifizieren und beschreiben. Die Beschreibung von Objekten besteht aus relevanten
Eigenschaften und Fähigkeiten. Wenn Sie wissen, was Sie brauchen, müssen Sie die
Beschreibung der Objekte in einer objektorientierten Programmiersprache wie zum Beispiel
C++ ausdrücken. Die praktische Umsetzung in C++ wird Ihnen im Folgenden noch gezeigt
werden.

Der große Vorteil der Objektorientierung ist, dass Sie als Entwickler fast keine
Abstraktionsleistung mehr erbringen müssen. Der Weg von der gedanklichen Problemlösung
zur Software ist enorm kurz. Während der Assembler-Programmierer sich auf die Eingabe
kryptischer Zeichen konzentrieren muss und der Basic-Programmierer sich den
Informationsfluss im Programm vergegenwärtigen muss, verwendet der C++-Programmierer
einfach im Code die gleichen Objekte wie in seinem Kopf. Die objektorientierte
Programmierung geht also einen großen Schritt auf den Menschen, den Programmierer zu,
und erwartet nicht, dass der Programmierer die Problemlösung dem Computer in einer Form
eingibt, die sich zum großen Teil an der Hardware-Architektur orientiert. In der
Objektorientierung wird es erstmals möglich, dass der Entwickler dem Computer sagt, dass
er diese und jene Objekte verwenden möchte. Ist dies geschehen, arbeitet er nur noch mit
den Objekten und kümmert sich nicht weiter um die Hardware-Abhängigkeit.

Damit der Computer objektorientierte Programme ausführen kann, muss er wissen, wie die
verwendeten Objekte im Programm genau aussehen, welche Eigenschaften und Fähigkeiten
sie besitzen. Sie müssen also vor der Verwendung eines Objekts dieses beschreiben. Eine
Objektbeschreibung wird in der Objektorientierung als Klasse bezeichnet. Eine Klasse ist
nichts anderes als die Beschreibung eines Objekts; also ein Plan, der festlegt, welche
Eigenschaften und Fähigkeiten das Objekt besitzen soll.
Während eine Klasse lediglich eine Objektbeschreibung ist, ist ein Objekt sozusagen eine
lebendig gewordene Klasse. Ein Synonym für Objekt ist Instanz. Objekte und Instanzen
basieren auf einer Klasse, die sie beschreiben. Objekte und Instanzen besitzen die
Eigenschaften und Fähigkeiten, die in der Klasse, auf der sie basieren, festgelegt worden
sind.

Sie können sich den Unterschied zwischen Klassen und Objekten gut anhand folgendem
Beispiel vorstellen. Um ein Haus zu bauen müssen Sie erstmal einen Architekten
beauftragen, einen Grundriss zu erstellen. In diesen Plan werden die Räume, der Ort von
Fenstern und Türen, Steckdosen und so weiter eingezeichnet. Dieser Plan beschreibt nach
seiner Fertigstellung komplett das Haus.

Nur weil Sie jedoch jetzt einen Plan vom Haus haben, ist dieses noch lange nicht erbaut.
Einziehen können Sie noch nicht. Das Haus muss erst errichtet werden. Ist dies geschehen
und haben die Bauarbeiter ordentlich gearbeitet, entspricht das Haus genau der Zeichnung
des Architekten.

In der Objektorientierung ist der Plan des Architekten die Klasse, das errichtete Haus das
Objekt bzw. die Instanz. So wie Sie anhand des Grundrisses weitere Häuser bauen können,
die alle identisch aussehen, können Sie basierend auf einer Klasse mehrere Objekte
erstellen. Es handelt sich wie bei den Häusern um unabhängige und getrennte Objekte, die
jedoch alle gleich aussehen und gleiche Eigenschaften und Fähigkeiten besitzen.

Sie können sich den Zusammenhang zwischen Klassen und Objekten auch wie folgt
vorstellen: Eine Klasse ist eine Art oder Gattung, und ein Objekt ist ein konkretes Exemplar
der Art. Bienen besitzen einen schwarz-gelb gestreiften Körper und die Fähigkeit zu fliegen.
Gestochen werden Sie jedoch immer von einer ganz konkreten Biene. Der BMW 316ti hat
eine Nennleistung von 85 kW und beschleunigt von 0 auf 100 km/h in 10,9 Sekunden. Der
316ti BMW, der in Ihrer Garage steht, ist ein Objekt dieser Klasse.

Als objektorientierter Programmierer müssen Sie immer wie folgt vorgehen: Zuerst erstellen
Sie die Klasse, dann basierend auf der Klasse das oder die benötigten Objekte. Ohne Klasse
sprich ohne Objektbeschreibung können Sie logischerweise kein Objekt erstellen.

Das Tolle an der Objektorientierung ist also, dass Sie Objekte aus der Wirklichkeit in Ihr
Programm mithinübernehmen können. Anstatt sich mit der Hardware herumzuschlagen und
das Spiel nach den Regeln des Computers zu spielen arbeiten Sie einfach innerhalb der
Software mit den gleichen Objekten, die Ihnen in der Problemlösung im Kopf rumschwirren.

Die Objektorientierung ist ein Meilenstein verglichen mit der prozeduralen Programmierung.
Sie haben es vielleicht schon vermutet: So einfach wie sich alles anhört ist es jedoch in der
Praxis nicht. Auch wenn die Objektorientierung viele Probleme löst, so schafft sie auch neue.
Als objektorientierter Programmierer stehen Sie vor verschiedenen Problemen: Welche
Objekte brauche ich tatsächlich zur Lösung einer Aufgabenstellung? Und welche
Eigenschaften und Methoden brauche ich tatsächlich in einem Objekt, um es sinnvoll
anwenden zu können?

Wenn Sie sich nochmal die Software für den Bankautomaten vergegenwärtigen: Reichen als
Objekte Kunde und Bank wirklich aus? Oder sollten nicht zusätzliche Objekte wie
Benutzerschnittstelle, Geldbetrag, Kontostand, Geldkarte und so weiter verwendet werden?
Damit könnten die Objekte Kunde und Bank etwas verkleinert werden, indem Informationen
in anderen Objekten gespeichert werden. Während die Objekte übersichtlicher werden,
wächst jedoch die Anzahl der Objekte im Programm insgesamt, was irgendwann auch
unübersichtlich wird.

Während der Kunde keine Eigenschaft Haarfarbe benötigt, hatten wir ihm eine Eigenschaft
PIN spendiert. Welche Eigenschaften sind noch wichtig? Kontostand, Limit zum Überziehen
des Kontos, Gültigkeitsdatum der Karte?

Das Herausarbeiten der notwendigen Objekte und Festlegen von Eigenschaften und
Fähigkeiten kann zum Teil enorm schwierig sein. Es können auch mehrere Lösungen
gefunden werden, bei denen am Anfang kaum abzusehen ist, welche die beste ist. Das
Herausarbeiten der richtigen Objekte, Eigenschaften und Fähigkeiten und die Konstruktion
der Zusammenhänge, um letztendlich zu einem sinnvollen Programm zu gelangen, hat eine
eigene Softwareindustrie geschaffen. Programme, die Entwicklern helfen, sinnvolle
Objektmodelle zu erstellen und zu pflegen, sind vor allem in größeren Projektvorhaben
immens wichtig und können vierstellige Beträge kosten.

Die Objektorientierung hat neben dem ganz entscheidenden Vorteil der Abbildung von
Objekten noch andere Stärken.

   •   Perfekte Klassen kapseln Daten. Andere Klassen können also nie direkt auf eigene
       Daten zugreifen. Die Interaktion zwischen Objekten, die auf Klassen basieren,
       geschieht nicht über Datenzugriffe, sondern über den Zugriff auf Fähigkeiten. Der
       Kunde in unserem Beispiel ruft die Fähigkeit Kontostand verringern der Klasse Bank
       auf anstatt selber den Kontostand neu zu berechnen. Das ist allein Aufgabe der
       Klasse Bank, und keine andere Klasse sollte in dessen Daten reinpfuschen. Die
       objektorientierte Programmiersprache Smalltalk zwingt den Entwickler zum Erstellen
       perfekter Objekte, in denen alle Daten gekapselt sind, weil direkte Datenzugriffe
       nicht unterstützt werden. In C++ entscheidet der Programmierer mit Hilfe
       sogenannter Zugriffsattribute selbst, ob er das Konzept der Datenkapselung verfolgt
       oder nicht.
   •   Klassen vererben Eigenschaften und Fähigkeiten an andere Klassen. Durch Vererbung
       können Klassenhierarchien erstellt werden, in denen jede Klasse von einer anderen
       Klasse erbt und an der Spitze der Klassenhierarchie eine oder mehrere Elternklassen
       stehen. Vererbung hat den Vorteil, dass Klassen austauschbar werden, weil sie eine
       gemeinsame Schnittstelle besitzen, wenn sie von der gleichen Elternklasse
       abstammen. C++ unterstützt im Gegensatz zu Java die Mehrfachvererbung: Eine
       Klasse kann mehr als eine Elternklasse haben und somit mehrere Schnittstellen
       erben. Im Kapitel 3, Vererbung lernen Sie die Vererbung genauer kennen.
   •   Die Programmiersprache C++ ist keine 100%ig objektorientierte
       Programmiersprache. Sie können auch C++-Programme erstellen, in denen keine
       einzige Klasse und kein einziges Objekt vorkommt. Sie können mehr oder weniger
       beliebig die Regeln der Objektorientierung außer Kraft setzen. Wenn Ihnen etwas
       nicht passt, wie es in der Objektorientierung vorgesehen ist, dann müssen Sie es in C+
       + höchstwahrscheinlich auch nicht so machen. Die Programmiersprache Smalltalk ist
hier viel rigoroser: Entweder Sie halten sich an die Regeln oder Sie wechseln die
       Programmiersprache.

Die extrem hohe Flexibilität von C++ ist wohl der wichtigste Grund, warum diese
Programmiersprache den größten Marktanteil und die größte Beliebtheit unter den
objektorientierten Sprachen besitzt. In C++ können Sie, müssen aber nicht alle
Sprachmerkmale verwenden, die für eine objektorientierte Entwicklung zur Verfügung
stehen. Das führt bei C++-Anfängern leicht zur Verwirrung: Alles scheint irgendwie optional
zu sein und auch anders zu gehen. Hier hilft nur Üben, Üben, Üben. Je mehr Programme Sie
in C++ erstellen, umso schneller erkennen Sie Vor- und Nachteile der verschiedenen Ansätze.
Erfahrung ist, wie bei allen Programmiersprachen, auch in C++ das Wichtigste.

1.3 Klassen entwickeln. Schlüsselwörter und ihre Bedeutung
Wie Sie bereits wissen, muss, bevor ein Objekt erstellt werden kann, erst eine Klasse
entwickelt werden. Ob Sie die Klasse selber programmieren oder ob sie von jemand
anderem entwickelt wurde und Sie sie beispielsweise aus dem offiziellen C++-Standard
übernehmen spielt keine Rolle - Hauptsache, sie ist da.

In C++ werden Klassendefinitionen normalerweise in Header-Dateien gepackt. Diese Dateien
erhalten der Übersicht wegen normalerweise den gleichen Namen wie die Klasse. So können
Sie beispielsweise davon ausgehen, dass in einer Header-Datei kunde.h eine Klasse kunde
liegt und in bank.h eine Klasse bank. Wann immer Sie nun Objekte basierend auf der Klasse
kunde oder der Klasse bank erstellen wollen, fügen Sie einfach über den Präprozessor-
Befehl #include die Header-Datei in die Quellcode-Datei ein - und schon können Sie die
Klasse verwenden, um darauf basierend ein Objekt zu erstellen.

Wie sieht jedoch eine Klassendefinition aus? Sie wissen, dass eine Klasse Eigenschaften und
Fähigkeiten festlegt. Wie definiert man das jedoch in C++?

#include <string>

class kunde
{
  public:
   void PIN_eingeben();

  private:
   std::string PIN;
};

Was Sie oben sehen ist eine Klassendefinition. Klassendefinitionen beginnen entweder mit
dem Schlüsselwort class oder struct. Den genauen Unterschied zwischen diesen beiden
Schlüsselwörtern werden Sie später kennenlernen. Hinter dem Schlüsselwort wird der Name
der Klasse angegeben. Obige Klasse heißt also kunde. Hinter dem Namen der Klasse folgen
zwei geschweifte Klammern, zwischen denen die Definition der Klasse steht. Vergessen Sie
nicht, hinter die geschlossene geschweifte Klammer ein Semikolon zu setzen - sonst meckert
der Compiler.
Obige Klasse besitzt eine Eigenschaft PIN und eine Fähigkeit, die PIN_eingeben() heißt. In
der objektorientierten Terminologie spricht man bei PIN auch tatsächlich von einer
Eigenschaft. Fähigkeiten werden jedoch Methoden genannt.

In technischer Hinsicht ist eine Eigenschaft nichts anderes als eine Variable. Es spielt auch
keine Rolle, ob die Variable einen intrinsischen Datentyp besitzt oder nicht. Eine Variable, die
innerhalb der geschweiften Klammern einer Klasse definiert ist, wird Eigenschaft genannt.

Methoden sind technisch nichts anderes als Funktionen. Funktionen, die innerhalb einer
Klasse definiert sind, heißen Methoden. So können auch objektorientierte Programmierer
ganz klar sagen, was sie meinen: Eine freistehende Funktion oder eine Funktion, die in einer
Klasse definiert ist.

Wenn Sie sich obige Klassendefinition ansehen, stellen Sie fest, dass die Methodendefinition
nicht vollständig ist. Es ist schließlich nur der Methodenkopf angegeben. Was die Methode
bei einem Aufruf eigentlich machen soll, steht nirgendwo. Die Klasse ist daher noch nicht
ausreichend definiert und kann so wie oben auch nicht eingesetzt werden.

Die Implementation von Methoden wird normalerweise von der Klassendefinition getrennt.
Wenn eine Klasse kunde heißt, wird sie normalerweise in einer Datei kunde.h definiert. Die
Methodendefinitionen befinden sich dann normalerweise in einer Datei kunde.cpp. So
können Klasse und Dateien schnell zugeordnet werden.

#include "kunde.h"

void kunde::PIN_eingeben()
{
}

Der Inhalt der Datei kunde.cpp, um die Klasse kunde zu vervollständigen, könnte wie oben
aussehen. Die Klasse definiert eine einzige Methode PIN_eingeben(). Der Methodenkopf
muss angegeben werden gefolgt von zwei geschweiften Klammern - also genauso wie wenn
Sie eine freistehende Funktion definieren würden. Der einzige Unterschied: Nachdem es sich
um eine Methode handelt, die ja immer einer Klasse zugeordnet ist, müssen Sie den
Klassennamen gefolgt vom Zugriffsoperator :: vor den Methodennamen stellen. Wenn Sie
das nicht machen, würde es sich bei PIN_eingeben() um eine freistehende Funktion
handeln, die nicht der Klasse kunde zugeordnet ist. Damit wäre die Klasse kunde immer
noch nicht vollständig.

Anstatt die Implementation einer Methode von der Klasse, in der die Methode deklariert ist,
zu trennen, können Sie auch folgendes schreiben.

#include <string>

class kunde
{
  public:
   void PIN_eingeben()
   {
   }
private:
   std::string PIN;
};

Nun wird die Methode direkt innerhalb der Klasse kunde definiert und nicht mehr nur wie
vorher deklariert.

Es gibt einen minimalen Unterschied zwischen Methoden, die in einer Klasse nur deklariert
und in einer Klasse vollständig definiert sind. Methoden, deren Implementation innerhalb
einer Klasse liegt, heißen Inline-Methoden. Bei einem Aufruf einer Inline-Methode wird nicht
der Code angesprungen, sondern der Compiler kopiert den Code der Methode jeweils an die
Stellen der ausführbaren Datei, an denen die Methode verwendet wird. Inline-Methoden
tauschen Speicherplatz gegen Geschwindigkeit ein: Es sind keine Sprünge nötig, um Code
auszuführen. Dafür liegt der gleiche Code mehrfach in der ausführbaren Datei vor, so dass
sich der Speicherbedarf der Anwendung erhöht.

Sie können Inline-Methoden auch dann erstellen, wenn sich die Implementation einer
Methode außerhalb der Klasse befindet. Sie müssen dann der Methodendeklaration in der
Klasse das Schlüsselwort inline voranstellen.

#include <string>

class kunde
{
  public:
   inline void PIN_eingeben();

  private:
   std::string PIN;
};

Die Methode PIN_eingeben() ist in der Klasse zwar nur deklariert und nicht definiert.
Dennoch wird der Compiler den Code der Methode an all die Stellen in der ausführbaren
Datei kopieren, an denen die Methode aufgerufen wird - jedenfalls in der Theorie. In der
Praxis verstehen Compiler Inline-Methoden eher als Empfehlung und nicht als verbindliche
Vorgabe. Der Grund ist, dass Compiler normalerweise besser beurteilen können, wie Code
optimiert werden soll - unabhängig davon, ob Inline-Methoden verwendet werden oder
nicht.

In der Praxis werden für gewöhnlich Klassendefinition und Methodendefinitionen immer in
getrennte Dateien gelegt. Selbst für Inline-Methoden wird eher das Schlüsselwort inline
verwendet als dass die Methode innerhalb der Klasse komplett definiert wird. Der Vorteil
dieser Aufteilung ist, dass Sie anhand einer Klasse die Eigenschaften und Methoden ablesen
können, ohne dass Sie sich mit der Implementation der Methoden rumschlagen müssen. Die
Implementation interessiert Sie normalerweise nicht, wenn Sie Methoden für ein Objekt
aufrufen möchten. Die Implementation ist ja Aufgabe der Klasse. Sie müssen nur wissen,
welche Eigenschaften und Methoden die Klasse zur Verfügung stellt, um mit ihr arbeiten zu
können. Eine Klassendefinition ist also in diesem Fall eine Art Dokumentation für
Programmierer, die Aufschluss darüber gibt, welche Schnittstelle zur Verfügung steht.
1.4 Objekte anlegen. Klassen zum Leben erwecken
Wenn Sie eine Klasse definiert haben, haben Sie den ersten Schritt getan. Der zweite Schritt
besteht nun darin, auf die Klasse zuzugreifen und ein Objekt basierend auf der Klasse zu
erstellen.

Objekte anlegen ist extrem einfach. Es handelt sich hierbei schlichtweg um Variablen, deren
Datentyp eine Klasse ist. Das ist die Definition eines Objekts. Um also ein Objekt zu erstellen,
gehen Sie so wie immer vor, wenn Sie eine Variable anlegen. Sie geben zuerst den Datentyp
an und dann den Namen der Variablen, in diesem Fall eben den Namen des Objekts.

#include "kunde.h"

kunde k;

Damit Sie ein Objekt vom Datentyp kunde erstellen können, müssen Sie den Datentyp
selbstverständlich erst bekanntmachen. Wenn Sie die Klasse in der Header-Datei kunde.h
definiert haben, fügen Sie diese einfach über den Präprozessorbefehl #include in Ihre
aktuelle Quellcode-Datei ein. Im obigen Beispiel wird also eine Variable k definiert, die
genaugenommen ein Objekt darstellt, und zwar vom Datentyp der Klasse kunde.

In der Klasse kunde haben Sie angegeben gehabt, dass es eine Methode PIN_eingeben()
gibt. Ihr Objekt besitzt also die Fähigkeit, eine PIN eingeben zu können. Wie greifen Sie
innerhalb von C++ auf diese Fähigkeit Ihres Objekts k zu?

Auf Eigenschaften und Methoden von Objekten wird über den Zugriffsoperator . zugegriffen.
Um also die Methode PIN_eingeben() für Ihr Objekt k aufzurufen, geben Sie folgende Zeile
an.

k.PIN_eingeben();

Diese Zeile ist letztendlich nichts anderes als der Aufruf einer Funktion - nur eben nicht einer
freistehenden Funktion, sondern einer, die innerhalb des Datentyps definiert ist, auf dem
das Objekt basiert, für das Sie die Funktion aufrufen. Das Objekt k basiert auf der Klasse
kunde, und diese Klasse besitzt eine Methode namens PIN_eingeben(), deren
Parameterliste leer ist. Obiger Methodenaufruf ist dementsprechend völlig korrekt und
würde vom Compiler ohne Meckern übersetzt werden.

Sie hatten ein paar Abschnitte zuvor einen anderen Zugriffsoperator kennengelernt, nämlich
::, um bei Methodendefinitionen angegeben zu können, zu welcher Klasse eine Methode
überhaupt gehört. Damit Sie nicht durcheinanderkommen: :: ist der Zugriffsoperator für
Klassen, . der Zugriffsoperator für Objekte.

1.5 Zugriffsrechte. Zugriff erlaubt oder nicht
Sie wissen, dass Sie über den Zugriffsoperator . auf Eigenschaften und Methoden eines
Objekts zugreifen können. Trotzdem würde der Compiler folgende Code-Zeile nicht
übersetzen.
k.PIN = "Abc";

Obwohl die Klasse kunde eine Eigenschaft PIN besitzt, können Sie nicht auf diese
Eigenschaft zugreifen. Die Eigenschaft PIN ist nämlich privat.

Die Programmiersprache C++ unterstützt zwei Zugriffsattribute: public und private. Auf
Eigenschaften und Methoden, die hinter public angegeben sind, darf von außerhalb der
Klasse zugegriffen werden. Auf Eigenschaften und Methoden, die hinter private angegeben
sind, darf nicht von außerhalb der Klasse zugegriffen werden. Private Eigenschaften und
Methoden sind also für die interne Verwendung in der Klasse gedacht. C++ unterstützt noch
ein drittes Zugriffsattribut, was jedoch nur im Zusammenhang mit Vererbung von Bedeutung
ist und daher erst in einem späteren Kapitel vorgestellt wird.

Erinnern Sie sich noch daran, dass für eine Klassendefinition in C++ zwei Schlüsselwörter zur
Verfügung stehen? Das eine Schlüsselwort, das in den allermeisten Fällen verwendet wird,
haben Sie bereits kennengelernt - es ist class. Anstatt eine Klasse mit class zu definieren,
können Sie auch das Schlüsselwort struct verwenden. Der einzige Unterschied zwischen
class und struct: In einer mit class definierten Klasse sind Eigenschaften und Methoden
standardmäßig privat, in einer mit struct definierten Klasse sind Eigenschaften und
Methoden standardmäßig öffentlich. Nachdem Sie mit den Zugriffsattributen private und
public jederzeit die Art des Zugriffs in einer Klasse festlegen können, können Sie Klassen auf
unterschiedliche Weise definieren.

class beispiel
{
   int Eigenschaft1;
   int Eigenschaft2;

  public:
   void Methode1();
   void Methode2();
};

Obige Klasse mit dem Namen beispiel definiert zwei private Eigenschaften und zwei
öffentliche Methoden. Wenn Sie die Klasse anstatt mit class mit struct definieren
möchten, schreiben Sie sie wie folgt.

struct beispiel
{
   void Methode1();
   void Methode2();

  private:
   int Eigenschaft1;
   int Eigenschaft2;
};

Beide Klassendefinitionen sind gleich. Der Compiler generiert jeweils den gleichen Code. Auf
welche Weise Sie Ihre Klassen definieren, spielt demnach keine Rolle. Es hat sich
eingebürgert, normalerweise class zu verwenden. Sie sollten struct nur dann einsetzen,
wenn Sie dokumentieren möchten, dass Ihre Klasse hauptsächlich aus öffentlichen
Eigenschaften und Methoden besteht und daher anderen Klassen ein sehr weiträumiger
Zugriff eingeräumt wird.

Sie können die Zugriffsattribute public und private auch mehrfach in einer
Klassendefinition verwenden. Sie sollten jedoch davon absehen und Eigenschaften und
Methoden, die dem gleichen Zugriffsmechanismus unterliegen, in einem Block
zusammenstellen, da dies die Übersicht erhöht.

1.6 Praxis-Beispiel. So geht's
In diesem Abschnitt werden die immer mal wieder als Beispiel in diesem Kapitel
angesprochenen Klassen kunde und bank verkomplettiert und in einer kleinen Anwendung
verwendet. Diese Anwendung simuliert einen Bankautomaten, an dem Sie Geld abheben
können.

Der Kunde muss nicht mehr nur die Fähigkeit besitzen, eine PIN eingeben zu können,
sondern er muss ebenfalls seine Geldkarte in den Automaten schieben und einen Betrag
auswählen können. Die Klasse kunde wird daher erweitert, so dass sie wie folgt aussieht.

#include <string>

class kunde
{
  public:
   void geldkarte_einschieben();
   void PIN_eingeben();
   void betrag_waehlen();

  private:
   std::string PIN;
};

Die Implementierung der Methoden wird wie üblich in einer anderen Datei vorgenommen.
Die Methode PIN_eingeben() bekommt nun außerdem einen sinnvolleren
Methodenrumpf verpasst, nachdem sie ja bisher keine Anweisungen enthalten hat und
daher bei einem Aufruf nichts geschehen wäre.

Die Methode geldkarte_einschieben() kann einen derartigen Vorgang natürlich nur
simulieren. Sie haben höchstwahrscheinlich kein Kartenlesegerät an Ihren Computer
angeschlossen. Die Programmierung von Kartenlesegeräten ist außerdem extrem
kompliziert, nachdem Sie hier in völligem Gegensatz zur Objektorientierung sehr
hardwarenah programmieren müssen. Unsere Methode geldkarte_einschieben()
simuliert den Vorgang dadurch, dass Sie einfach einen Benutzernamen eingeben müssen.

#include "kunde.h"
#include <iostream>
#include <string>

void kunde::geldkarte_einschieben()
{
  std::string Benutzername;
  std::cout << "Schieben Sie bitte Ihre Karte in den Automaten: " << std::flush;
std::cin >> Benutzername;
}

void kunde::PIN_eingeben()
{
  std::cout << "Geben Sie Ihre PIN ein: " << std::flush;
  std::cin >> PIN;
}

void kunde::betrag_waehlen()
{
  int Betrag;
  std::cout << "Geben Sie ein, wieviel Geld Sie abheben moechten: " << std::flush;
  std::cin >> Betrag;
}

In den drei Methoden wird jeweils auf die Standardein- und -ausgabe zugegriffen, so dass
die Header-Datei iostream eingebunden werden muss. Die Methode
geldkarte_einschieben() legt ein Objekt vom Typ std::string an. Daher muss außerdem
die Header-Datei string mit #include eingebunden werden.

Alle drei Methoden geben einen Text auf die Standardausgabe aus und erwarten eine
Eingabe vom Anwender. Sehen Sie sich die Methode PIN_eingeben() genau an. Es werden
Daten von der Standardeingabe eingelesen und in einer Variablen PIN gespeichert, die gar
nicht in der Methode definiert ist.

Der Compiler meckert trotzdem nicht. PIN ist eine Eigenschaft der Klasse kunde und dort
definiert. Jede Methode einer Klasse kann jederzeit auf Eigenschaften in einer Klasse
zugreifen. In diesem Fall wird also die Eingabe des Anwenders in einer Eigenschaft
gespeichert und nicht in einer lokalen Variable.

Übrigens: Die Eigenschaft PIN ist eine private Eigenschaft. Zugriffsattribute wie private und
public schränken den Zugriff auf Eigenschaften und Methoden nur gegenüber anderen
Klassen ein. Eine Methode in einer Klasse kann grundsätzlich auf alle Eigenschaften und
Methoden zugreifen, völlig egal, mit welchen Zugriffsattributen sie geschützt sind.
Zugriffsattribute schränken nur den Zugriff von außen ein.

Der Vorteil von Eigenschaften ist, dass sie einen größeren Gültigkeitsbereich haben als lokale
Variablen. Die Eigenschaft PIN existiert genauso lange wie das Objekt, das auf der Klasse
kunde basiert. Wenn der Anwender eine PIN eingegeben hat und die Methode
PIN_eingeben() beendet wurde, ist die Eingabe des Anwenders immer noch in der
Eigenschaft PIN gespeichert. Dies ist bei den Methoden geldkarte_einschieben() und
betrag_waehlen() nicht der Fall: Dort werden Eingaben des Anwenders in lokalen
Variablen gespeichert, die nach Ende der Methode aus dem Speicher gelöscht werden. Ihr
Gültigkeitsbereich erstreckt sich lediglich über die Methoden und nicht weiter. Die
Methoden geldkarte_einschieben() und betrag_waehlen() müssen später
nachbearbeitet werden, wenn feststeht, wie die Klasse kunde und deren Methoden mit der
Klasse bank zusammenarbeiten.

Im nächsten Schritt wird daher die Klasse bank definiert. Die Klasse bank muss Daten zum
Konto verwalten, damit zum einen überprüft werden kann, ob der Zugang zum Konto durch
den Kunden am Bankautomaten in Ordnung geht, und zum anderen verhindert werden
kann, dass der Kunde unendlich viel Geld abhebt. Die Klasse bank wird daher in einem
ersten Schritt wie folgt definiert.

#include <string>

class bank
{
  private:
   std::string Benutzername;
   std::string PIN;
   int Kontostand;
};

Welche Fähigkeiten müssen der Bank spendiert werden? Sie muss überprüfen, ob der vom
Kunden eingegebene Benutzername und die PIN zusammenpassen und der Zugang
gewährleistet wird. Sie muss außerdem bei einer Bargeldabhebung den Kontostand
verringern und gegebenenfalls die Auszahlung verhindern, falls das Konto überzogen wird.
Die Klasse bank wird daher wie folgt erweitert.

#include <string>

class bank
{
  public:
   bool zugriff_ueberpruefen(std::string benutzername, std::string pin);
   bool geld_abheben(int betrag);

  private:
   std::string Benutzername;
   std::string PIN;
   int Kontostand;
};

Die Klasse bank erhält zwei Methoden zugriff_ueberpruefen() und geld_abheben().
Beide Methoden geben einen Wahrheitswert zurück, der angibt, ob der Zugriff in Ordnung
geht bzw. ob das Geld abgehoben werden konnte. Um den Zugriff überprüfen zu können,
werden der Methode zugriff_ueberpruefen() beim Aufruf zwei Werte übergeben -
nämlich der Benutzername und die PIN, die der Anwender eingegeben hat. Der Methode
geld_abheben() wird ein Parameter vom Typ int übergeben, der den Betrag angibt, den
der Kunde abheben möchte.

Was noch fehlt ist eine Möglichkeit, die Eigenschaften der Klasse bank zu initialisieren.
Deswegen wird der Klasse bank eine Methode init() spendiert, die ganz am Anfang des
Programms aufgerufen werden muss und festlegt, mit welchen Werten die Eigenschaften
Benutzername, PIN und Kontostand vorbelegt werden.

#include <string>

class bank
{
  public:
   void init(std::string benutzername, std::string pin, int kontostand);
   bool zugriff_ueberpruefen(std::string benutzername, std::string pin);
bool geld_abheben(int betrag);

  private:
   std::string Benutzername;
   std::string PIN;
   int Kontostand;
};

Nun fehlt noch die Implementierung der Methoden.

#include "bank.h"

void bank::init(std::string benutzername, std::string pin, int kontostand)
{
  Benutzername = benutzername;
  PIN = pin;
  Kontostand = kontostand;
}

bool bank::zugriff_ueberpruefen(std::string benutzername, std::string pin)
{
  if (Benutzername == benutzername && PIN == pin)
  {
    return true;
  }

    return false;
}

bool bank::geld_abheben(int betrag)
{
  if (Kontostand >= betrag)
  {
    Kontostand -= betrag;
    return true;
  }

    return false;
}

Die Methode init() setzt lediglich die Eigenschaften auf die Werte, die als Parameter
übergeben werden. Die Methode zugriff_ueberpruefen() vergleicht den als Parameter
übergebenen Benutzernamen und die PIN mit den Eigenschaften des Objekts und gibt true
oder false zurück. In der Methode geld_abheben() wird zuerst überprüft, ob der Betrag,
den der Kunde abheben möchte, nicht den aktuellen Kontostand übersteigt. Ist dies nicht
der Fall, wird der Kontostand neuberechnet und true zurückgegeben - andernfalls false.

Die Klasse bank ist somit fertig. Wir müssen uns nun wieder der Klasse kunde zuwenden
und sie vervollständigen bzw. den Zugriff auf die Bank hinzufügen. Die Klasse kunde muss
hierzu ein wenig umgebaut werden. Die Eingabe des Benutzernamens, der ja die Geldkarte
simuliert, muss in einer Eigenschaft in der Klasse gespeichert werden. Andernfalls kann in
der Methode PIN_eingeben() die Bank gar nicht den Zugriff überprüfen, wenn der
eingegebene Benutzername nirgendwo dauerhaft gespeichert wird.
Die Methde PIN_eingeben() soll außerdem zurückgeben, ob die Bank den Zugriff gestattet
oder nicht. Ist der Zugriff nämlich nicht gestattet, muss der Anwender seine Karte
entnehmen und sie neu einlegen. Im Programm muss also der Benutzername neu
eingegeben werden. Es darf nicht sein, dass der Kunde eine beliebige PIN eingibt, die Bank
den Zugriff nicht gestattet, der Kunde dann trotzdem Geld abheben kann. Die Methode
betrag_waehlen() soll ebenfalls zurückgeben, ob die Auszahlung erfolgreich war oder
nicht.

Die Definition der Klasse kunde ändert sich minimal. Lediglich Benutzername wird als neue
Eigenschaft hinzugefügt, und der Rückgabewert der Methoden PIN_eingeben() und
betrag_waehlen() wird angepasst.

#include <string>

class kunde
{
  public:
   void geldkarte_einschieben();
   bool PIN_eingeben();
   bool betrag_waehlen();

  private:
   std::string Benutzername;
   std::string PIN;
};

In die Implementierung der Methoden der Klasse kunde wird tiefergehend eingegriffen.

#include "kunde.h"
#include "bank.h"
#include <iostream>

bank b;

void kunde::geldkarte_einschieben()
{
  std::cout << "Schieben Sie bitte Ihre Karte in den Automaten: " << std::flush;
  std::cin >> Benutzername;
}

bool kunde::PIN_eingeben()
{
  std::cout << "Geben Sie Ihre PIN ein: " << std::flush;
  std::cin >> PIN;
  return b.zugriff_ueberpruefen(Benutzername, PIN);
}

bool kunde::betrag_waehlen()
{
  int Betrag;
  std::cout << "Geben Sie ein, wieviel Geld Sie abheben moechten: " << std::flush;
  std::cin >> Betrag;
  return b.geld_abheben(Betrag);
}
Beachten Sie zuallererst, dass in dieser Datei ein globales Objekt b vom Typ bank angelegt
wird. Zu diesem Zweck wird außerdem die Header-Datei bank.h eingebunden, um die
Klasse bekanntzumachen.

Die Methode geldkarte_einschieben() speichert den Benutzernamen nun nicht mehr in
einer lokalen Variablen, sondern in einer Eigenschaft. In der Methode PIN_eingeben() wird
dieser Benutzername zusammen mit der PIN an die Methode zugriff_ueberpruefen() des
Objekts b weitergegeben. Der Rückgabewert dieser Methode ist gleichzeitig der
Rückgabewert der Methode PIN_eingeben().

In der Methode betrag_waehlen() wird ebenfalls auf das Objekt b zugegriffen. Der
Methode geld_abheben() wird der vom Anwender eingegebene Geldbetrag übergeben,
der abgehoben werden soll. Der Rückgabewert dieser Methode ist wieder gleichzeitig der
Rückgabewert der Methode betrag_waehlen().

Das einzige, was noch fehlt, ist die Funktion main(), um das Programm starten zu können.
Die Funktion sieht wie folgt aus.

#include "kunde.h"
#include "bank.h"
#include <iostream>

extern bank b;

int main()
{
  kunde k;

    b.init("boris", "1234", 1000);

    for (;;)
    {
      k.geldkarte_einschieben();

        if (k.PIN_eingeben() == true)
        {
          if (k.betrag_waehlen() == true)
          {
            std::cout << "Der gewuenschte Betrag wurde abgehoben." << std::endl;
          }
        }
        else
        {
          std::cout << "Die PIN ist falsch." << std::endl;
        }
    }
}

In der Funktion main() wird ein Objekt vom Typ kunde angelegt. Danach wird das Objekt b
initialisiert, indem die Methode init() aufgerufen wird. Beachten Sie, wie auf das Objekt
zugegriffen wird. Es wird vor der Funktion main() mit dem Schlüsselwort extern
bekanntgemacht. Dies bedeutet, dass innerhalb dieser Datei auf ein Objekt b zugegriffen
werden kann, das in einer anderen Datei angelegt wird. Sehen Sie sich kunde.cpp an: In der
Datei, in der die Methoden der Klasse kunde definiert sind, wird ein Objekt b erstellt. Auf
dieses Objekt wird nun in der Funktion main() zugegriffen, um es zu initialisieren. Würden
Sie das Schlüsselwort extern weglassen, würden Sie ein neues Objekt namens b anlegen.
Der Compiler würde daraufhin den Code nicht übersetzen, da es zwei gleichnamige Objekte
im gleichen Gültigkeitsbereich geben würde. Sie müssen daher extern angeben.

Nachdem das Objekt b initialisiert wurde, wird eine Endlosschleife mit for gestartet. Wenn
Sie das C++-Programm starten, können Sie es ausschließlich mit der Tastenkombination
Strg+C abbrechen. Nachdem ein Bankautomat für gewöhnlich auch nicht beendet oder
heruntergefahren wird, ist die Endlosschleife in diesem Fall in Ordnung.

In der Endlosschleife wird auf das Objekt k zugegriffen. Es werden nacheinander die drei
Methoden aufgerufen, die für dieses Objekt definiert sind. Für die Methoden
PIN_eingeben() und betrag_waehlen() wird jedoch der Rückgabewert überprüft. Denn
daran erkennt das Programm, ob der Zugriff auf das Bankkonto gestattet ist und der
eingegebene Betrag abgehoben werden konnte. Wird eine falsche PIN eingegeben, wird der
Kunde erst gar nicht aufgefordert, einen Betrag zu wählen. Stimmt die PIN und der Kunde
versucht, mehr Geld abzuheben als auf dem Konto liegt, erfolgt die Abbuchung nicht. Der
Bankautomat zeigt in diesem Fall auch keine entsprechende Bestätigung des
Abbuchungsvorgangs an.

Das Programm ist nun fertig. Sie können es starten und ausprobieren. Geben Sie als
Benutzernamen boris und als PIN 1234 ein, um Zugriff auf das Bankkonto zu erhalten. Von
dort können Sie insgesamt 1000 Euro abheben. Dies sind die Werte, mit denen die Bank in
init() initialisiert wurde.

Copyright © 2001-2010 Boris Schäling

Weitere ähnliche Inhalte

Andere mochten auch

Nl 09 marketing y crisis
Nl 09 marketing y crisisNl 09 marketing y crisis
Nl 09 marketing y crisisRicardo Uribe
 
Business Brief - Tech Trends
Business Brief - Tech TrendsBusiness Brief - Tech Trends
Business Brief - Tech TrendsDave Newbold
 
SARONIA - Feedback Recap V5
SARONIA - Feedback Recap V5SARONIA - Feedback Recap V5
SARONIA - Feedback Recap V5Team Saronia
 
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerdenwissensbuch
 
BARONG KNIFE AND MACHETE
BARONG KNIFE AND MACHETEBARONG KNIFE AND MACHETE
BARONG KNIFE AND MACHETEFranz Muhlfeld
 
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...Miguel A. Amutio
 
Llegan los nuevos neumáticos
Llegan los nuevos neumáticosLlegan los nuevos neumáticos
Llegan los nuevos neumáticosPedro Gomez
 
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...Finmeccanica
 
Formaciondiapositivasdespues 120521181849-phpapp01
Formaciondiapositivasdespues 120521181849-phpapp01Formaciondiapositivasdespues 120521181849-phpapp01
Formaciondiapositivasdespues 120521181849-phpapp01Cindy Gonzalez
 

Andere mochten auch (19)

Tunel capriano
Tunel caprianoTunel capriano
Tunel capriano
 
Nl 09 marketing y crisis
Nl 09 marketing y crisisNl 09 marketing y crisis
Nl 09 marketing y crisis
 
Business Brief - Tech Trends
Business Brief - Tech TrendsBusiness Brief - Tech Trends
Business Brief - Tech Trends
 
Unidad 5 (1)
Unidad 5 (1)Unidad 5 (1)
Unidad 5 (1)
 
1ª 2a-y3a-juany judas
1ª 2a-y3a-juany judas1ª 2a-y3a-juany judas
1ª 2a-y3a-juany judas
 
R 9
R 9R 9
R 9
 
SARONIA - Feedback Recap V5
SARONIA - Feedback Recap V5SARONIA - Feedback Recap V5
SARONIA - Feedback Recap V5
 
Vocabulario
VocabularioVocabulario
Vocabulario
 
Redes ....
Redes ....Redes ....
Redes ....
 
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden
"Kriegen das eigentlich alle?": Mindmaps über das Erwachsenwerden
 
BARONG KNIFE AND MACHETE
BARONG KNIFE AND MACHETEBARONG KNIFE AND MACHETE
BARONG KNIFE AND MACHETE
 
Plenaria
PlenariaPlenaria
Plenaria
 
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...
XII Jornadas CERES, situación y evolución del Esquema Nacional de Interoperab...
 
Van Gogh
Van GoghVan Gogh
Van Gogh
 
Llegan los nuevos neumáticos
Llegan los nuevos neumáticosLlegan los nuevos neumáticos
Llegan los nuevos neumáticos
 
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...
Dwt simulation als mittel zur erkenntnisgewinnung zum fähigkeitsaufbau für de...
 
Haiti
HaitiHaiti
Haiti
 
Fase planificación slides opercion triunfo
Fase planificación slides opercion triunfoFase planificación slides opercion triunfo
Fase planificación slides opercion triunfo
 
Formaciondiapositivasdespues 120521181849-phpapp01
Formaciondiapositivasdespues 120521181849-phpapp01Formaciondiapositivasdespues 120521181849-phpapp01
Formaciondiapositivasdespues 120521181849-phpapp01
 

Ähnlich wie Klassen

Dnug dresden blend 5. 5. 2010
Dnug dresden blend 5. 5. 2010Dnug dresden blend 5. 5. 2010
Dnug dresden blend 5. 5. 2010SharepointUGDD
 
DNUG Dresden Blend
DNUG Dresden BlendDNUG Dresden Blend
DNUG Dresden BlendMartin Hey
 
Script hydroinformatik i
Script hydroinformatik iScript hydroinformatik i
Script hydroinformatik icuitla68
 
Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013superflomo
 
Mit Domain-driven Design (DDD) nützliche und flexible Software bauen
Mit Domain-driven Design (DDD) nützliche und flexible Software bauenMit Domain-driven Design (DDD) nützliche und flexible Software bauen
Mit Domain-driven Design (DDD) nützliche und flexible Software bauenDigicomp Academy AG
 
Projektmanagement 200420
Projektmanagement 200420Projektmanagement 200420
Projektmanagement 200420Claus Brell
 
Architektur = Kommunikation
Architektur = KommunikationArchitektur = Kommunikation
Architektur = KommunikationMatthias Bohlen
 
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012Martin Seibert
 
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...Andreas Wissel
 
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)TANNER AG
 
Anforderungen klar kommunizieren
Anforderungen klar kommunizierenAnforderungen klar kommunizieren
Anforderungen klar kommunizierenDaniel Andrisek
 
Onno Reiners: E-Learning einfach selbst erstellen
Onno Reiners: E-Learning einfach selbst erstellenOnno Reiners: E-Learning einfach selbst erstellen
Onno Reiners: E-Learning einfach selbst erstellenlernet
 
JavaScript: Von einfachen Scripten zu komplexen Anwendungen
JavaScript: Von einfachen Scripten zu komplexen AnwendungenJavaScript: Von einfachen Scripten zu komplexen Anwendungen
JavaScript: Von einfachen Scripten zu komplexen Anwendungenmolily
 
Softwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha NightSoftwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha NightChristinaLerch1
 
20100830 my ple
20100830 my ple20100830 my ple
20100830 my pleheiko.vogl
 
Domain-Driven Design und Hexagonale Architektur
Domain-Driven Design und Hexagonale ArchitekturDomain-Driven Design und Hexagonale Architektur
Domain-Driven Design und Hexagonale ArchitekturTorben Fojuth
 
Dokumentation
DokumentationDokumentation
Dokumentationo0plum0o
 

Ähnlich wie Klassen (20)

GUIs mit Expression Blend
GUIs mit Expression BlendGUIs mit Expression Blend
GUIs mit Expression Blend
 
Dnug dresden blend 5. 5. 2010
Dnug dresden blend 5. 5. 2010Dnug dresden blend 5. 5. 2010
Dnug dresden blend 5. 5. 2010
 
DNUG Dresden Blend
DNUG Dresden BlendDNUG Dresden Blend
DNUG Dresden Blend
 
Script hydroinformatik i
Script hydroinformatik iScript hydroinformatik i
Script hydroinformatik i
 
Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013
 
Android doc
Android docAndroid doc
Android doc
 
Mit Domain-driven Design (DDD) nützliche und flexible Software bauen
Mit Domain-driven Design (DDD) nützliche und flexible Software bauenMit Domain-driven Design (DDD) nützliche und flexible Software bauen
Mit Domain-driven Design (DDD) nützliche und flexible Software bauen
 
Projektmanagement 200420
Projektmanagement 200420Projektmanagement 200420
Projektmanagement 200420
 
Domain-Driven Design
Domain-Driven DesignDomain-Driven Design
Domain-Driven Design
 
Architektur = Kommunikation
Architektur = KommunikationArchitektur = Kommunikation
Architektur = Kommunikation
 
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012
Agiles Schätzen im Team - Joachim Seibert, OBJEKTspektrum 5/2012
 
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
Robuste Design Systems mit Storybook und Angular: vom Konzept zur lebendigen ...
 
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)
9. TANNER-Hochschulwettbewerb | Beitrag Team Kilpert (HS Merseburg)
 
Anforderungen klar kommunizieren
Anforderungen klar kommunizierenAnforderungen klar kommunizieren
Anforderungen klar kommunizieren
 
Onno Reiners: E-Learning einfach selbst erstellen
Onno Reiners: E-Learning einfach selbst erstellenOnno Reiners: E-Learning einfach selbst erstellen
Onno Reiners: E-Learning einfach selbst erstellen
 
JavaScript: Von einfachen Scripten zu komplexen Anwendungen
JavaScript: Von einfachen Scripten zu komplexen AnwendungenJavaScript: Von einfachen Scripten zu komplexen Anwendungen
JavaScript: Von einfachen Scripten zu komplexen Anwendungen
 
Softwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha NightSoftwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha Night
 
20100830 my ple
20100830 my ple20100830 my ple
20100830 my ple
 
Domain-Driven Design und Hexagonale Architektur
Domain-Driven Design und Hexagonale ArchitekturDomain-Driven Design und Hexagonale Architektur
Domain-Driven Design und Hexagonale Architektur
 
Dokumentation
DokumentationDokumentation
Dokumentation
 

Mehr von tutego

Der C++ Standard
Der C++ StandardDer C++ Standard
Der C++ Standardtutego
 
CSS Seminar
CSS SeminarCSS Seminar
CSS Seminartutego
 
Schulung jQuery JavaScript-Bibliothek
Schulung jQuery JavaScript-BibliothekSchulung jQuery JavaScript-Bibliothek
Schulung jQuery JavaScript-Bibliothektutego
 
Schulung C++ Boost Bibliotheken
Schulung C++ Boost BibliothekenSchulung C++ Boost Bibliotheken
Schulung C++ Boost Bibliothekentutego
 
SQL-Updates mit der JDBC-API
SQL-Updates mit der JDBC-APISQL-Updates mit der JDBC-API
SQL-Updates mit der JDBC-APItutego
 
Die JSTL Tag-Library
Die JSTL Tag-LibraryDie JSTL Tag-Library
Die JSTL Tag-Librarytutego
 
Fundamentale Muster in Java
Fundamentale Muster in JavaFundamentale Muster in Java
Fundamentale Muster in Javatutego
 
JdbcTemplate aus Spring
JdbcTemplate aus SpringJdbcTemplate aus Spring
JdbcTemplate aus Springtutego
 
Schieberegler und analoge Anzeigen in Swing
Schieberegler und analoge Anzeigen in Swing Schieberegler und analoge Anzeigen in Swing
Schieberegler und analoge Anzeigen in Swing tutego
 
Einführung in den EventBus
Einführung in den EventBusEinführung in den EventBus
Einführung in den EventBustutego
 
Erweiteres for (foreach) in Java 5
Erweiteres for (foreach) in Java 5Erweiteres for (foreach) in Java 5
Erweiteres for (foreach) in Java 5tutego
 
Autoboxing in Java 5
Autoboxing in Java 5Autoboxing in Java 5
Autoboxing in Java 5tutego
 

Mehr von tutego (12)

Der C++ Standard
Der C++ StandardDer C++ Standard
Der C++ Standard
 
CSS Seminar
CSS SeminarCSS Seminar
CSS Seminar
 
Schulung jQuery JavaScript-Bibliothek
Schulung jQuery JavaScript-BibliothekSchulung jQuery JavaScript-Bibliothek
Schulung jQuery JavaScript-Bibliothek
 
Schulung C++ Boost Bibliotheken
Schulung C++ Boost BibliothekenSchulung C++ Boost Bibliotheken
Schulung C++ Boost Bibliotheken
 
SQL-Updates mit der JDBC-API
SQL-Updates mit der JDBC-APISQL-Updates mit der JDBC-API
SQL-Updates mit der JDBC-API
 
Die JSTL Tag-Library
Die JSTL Tag-LibraryDie JSTL Tag-Library
Die JSTL Tag-Library
 
Fundamentale Muster in Java
Fundamentale Muster in JavaFundamentale Muster in Java
Fundamentale Muster in Java
 
JdbcTemplate aus Spring
JdbcTemplate aus SpringJdbcTemplate aus Spring
JdbcTemplate aus Spring
 
Schieberegler und analoge Anzeigen in Swing
Schieberegler und analoge Anzeigen in Swing Schieberegler und analoge Anzeigen in Swing
Schieberegler und analoge Anzeigen in Swing
 
Einführung in den EventBus
Einführung in den EventBusEinführung in den EventBus
Einführung in den EventBus
 
Erweiteres for (foreach) in Java 5
Erweiteres for (foreach) in Java 5Erweiteres for (foreach) in Java 5
Erweiteres for (foreach) in Java 5
 
Autoboxing in Java 5
Autoboxing in Java 5Autoboxing in Java 5
Autoboxing in Java 5
 

Klassen

  • 1. Kurs: Objektorientiertes Programmieren mit C++ (http://tutego.de/g/CPP1) Autor: Boris Schäling Kapitel 1: Klassen und Objekte Inhaltsverzeichnis • 1.1 Allgemeines • 1.2 Überblick • 1.3 Klassen entwickeln • 1.4 Objekte anlegen • 1.5 Zugriffsrechte • 1.6 Praxis-Beispiel 1.1 Allgemeines. Konzepte und praktische Umsetzung In der objektorientierten Programmierung wird mit Begriffen wie Klassen, Objekten, Instanzen, Vererbung, Kapselung und so weiter nur so um sich geschmissen. In diesem Kapitel erhalten Sie einen Überblick über die einzelnen Bestandteile der Objektorientierung, wie diese zusammenhängen und vor allem welchen Sinn sie haben. Diese Übersicht gilt hierbei nicht nur für die Programmiersprache C++, sondern grundsätzlich auch für andere objektorientierte Sprachen. Nach dem Rundflug über die Objektorientierung werden Sie in die notwendige Syntax und Semantik eingewiesen, um einfache Klassen in C++ selbst zu erstellen. 1.2 Überblick. Objektorientierte Programmierung Um die objektorientierte Programmierung herrscht - vor allem bei Entwicklern, die nicht objektorientiert programmieren - ein Riesenhype. Die Objektorientierung scheint das Non- Plus-Ultra, der heilige Gral unter den Programmiersprachen zu sein. Objektorientiert- entwickelte Programme scheinen grundsätzlich besser als Anwendungen zu sein, die in einer nicht-objektorientierten Programmiersprache entwickelt sind. Woher kommt dieser Hype um die Objektorientierung? Bei der Objektorientierung stehen, wie der Name schon sagt, Objekte im Vordergrund. Ein Programm wird nicht mehr als eine Art Wasserfall betrachtet, in dem Informationen von oben nach unten fließen. Dieses Flusskonzept von Daten spielt in der Objektorientierung keine Rolle. Wird eine Aufgabenstellung objektorientiert gelöst, werden zuerst Objekte, die zur Lösung der Aufgabe miteinander agieren müssen, herausgearbeitet. Um objektorientiert programmieren zu können muss erstmal klar sein, was für Objekte eigentlich genau benötigt werden. Dies hängt natürlich von der Aufgabe ab. Soll beispielsweise eine Software für einen Bankautomaten zum Geldabheben objektorientiert entwickelt werden, könnten sich als notwendige Objekte zur Lösung der Aufgabe Kunde und Bank erweisen. Das Abheben von
  • 2. Geld ist schließlich ein Vorgang, bei dem ein Kunde Daten in einen Bankautomaten eingibt und elektronisch mit einer Bank kommuniziert. Eine objektorientierte Programmiersprache macht es nun möglich, den Kunden und die Bank hinüber in die Software zu nehmen. Das heißt, in einer objektorientierten Programmiersprache werden die Objekte, die herausgearbeitet wurden, direkt in den Code übernommen und dort nachgebildet. Dieses Nachbilden sieht derart aus, dass für die Lösung des Problems benötigte Eigenschaften und Fähigkeiten der Objekte in den Code übernommen werden. Zum Beispiel spielt für die Entwicklung der Bankautomatensoftware die Haarfarbe des Kunden keine Rolle. Ob er jedoch die PIN für sein Bankkonto kennt, ist wichtig. Daher könnte dem Objekt Kunde eine Eigenschaft PIN gegeben werden. Eine Eigenschaft Haarfarbe wäre unsinnig. Um die PIN vom Kunden zu erfahren, muss er sie dem Bankautomaten mitteilen. Der Kunde muss die Fähigkeit besitzen, eine PIN eingeben zu können. Diese Fähigkeit würde also dem entsprechenden Objekt Kunde in der Objektorientierung gegeben werden. Dass der Kunde außerdem beispielsweise tanzen kann, interessiert in diesem Zusammenhang nicht. Eine derartige Fähigkeit wird zum Geldabheben am Bankautomaten nicht benötigt. Als objektorientierter Entwickler müssen Sie also für die Aufgabenstellung relevante Objekte identifizieren und beschreiben. Die Beschreibung von Objekten besteht aus relevanten Eigenschaften und Fähigkeiten. Wenn Sie wissen, was Sie brauchen, müssen Sie die Beschreibung der Objekte in einer objektorientierten Programmiersprache wie zum Beispiel C++ ausdrücken. Die praktische Umsetzung in C++ wird Ihnen im Folgenden noch gezeigt werden. Der große Vorteil der Objektorientierung ist, dass Sie als Entwickler fast keine Abstraktionsleistung mehr erbringen müssen. Der Weg von der gedanklichen Problemlösung zur Software ist enorm kurz. Während der Assembler-Programmierer sich auf die Eingabe kryptischer Zeichen konzentrieren muss und der Basic-Programmierer sich den Informationsfluss im Programm vergegenwärtigen muss, verwendet der C++-Programmierer einfach im Code die gleichen Objekte wie in seinem Kopf. Die objektorientierte Programmierung geht also einen großen Schritt auf den Menschen, den Programmierer zu, und erwartet nicht, dass der Programmierer die Problemlösung dem Computer in einer Form eingibt, die sich zum großen Teil an der Hardware-Architektur orientiert. In der Objektorientierung wird es erstmals möglich, dass der Entwickler dem Computer sagt, dass er diese und jene Objekte verwenden möchte. Ist dies geschehen, arbeitet er nur noch mit den Objekten und kümmert sich nicht weiter um die Hardware-Abhängigkeit. Damit der Computer objektorientierte Programme ausführen kann, muss er wissen, wie die verwendeten Objekte im Programm genau aussehen, welche Eigenschaften und Fähigkeiten sie besitzen. Sie müssen also vor der Verwendung eines Objekts dieses beschreiben. Eine Objektbeschreibung wird in der Objektorientierung als Klasse bezeichnet. Eine Klasse ist nichts anderes als die Beschreibung eines Objekts; also ein Plan, der festlegt, welche Eigenschaften und Fähigkeiten das Objekt besitzen soll.
  • 3. Während eine Klasse lediglich eine Objektbeschreibung ist, ist ein Objekt sozusagen eine lebendig gewordene Klasse. Ein Synonym für Objekt ist Instanz. Objekte und Instanzen basieren auf einer Klasse, die sie beschreiben. Objekte und Instanzen besitzen die Eigenschaften und Fähigkeiten, die in der Klasse, auf der sie basieren, festgelegt worden sind. Sie können sich den Unterschied zwischen Klassen und Objekten gut anhand folgendem Beispiel vorstellen. Um ein Haus zu bauen müssen Sie erstmal einen Architekten beauftragen, einen Grundriss zu erstellen. In diesen Plan werden die Räume, der Ort von Fenstern und Türen, Steckdosen und so weiter eingezeichnet. Dieser Plan beschreibt nach seiner Fertigstellung komplett das Haus. Nur weil Sie jedoch jetzt einen Plan vom Haus haben, ist dieses noch lange nicht erbaut. Einziehen können Sie noch nicht. Das Haus muss erst errichtet werden. Ist dies geschehen und haben die Bauarbeiter ordentlich gearbeitet, entspricht das Haus genau der Zeichnung des Architekten. In der Objektorientierung ist der Plan des Architekten die Klasse, das errichtete Haus das Objekt bzw. die Instanz. So wie Sie anhand des Grundrisses weitere Häuser bauen können, die alle identisch aussehen, können Sie basierend auf einer Klasse mehrere Objekte erstellen. Es handelt sich wie bei den Häusern um unabhängige und getrennte Objekte, die jedoch alle gleich aussehen und gleiche Eigenschaften und Fähigkeiten besitzen. Sie können sich den Zusammenhang zwischen Klassen und Objekten auch wie folgt vorstellen: Eine Klasse ist eine Art oder Gattung, und ein Objekt ist ein konkretes Exemplar der Art. Bienen besitzen einen schwarz-gelb gestreiften Körper und die Fähigkeit zu fliegen. Gestochen werden Sie jedoch immer von einer ganz konkreten Biene. Der BMW 316ti hat eine Nennleistung von 85 kW und beschleunigt von 0 auf 100 km/h in 10,9 Sekunden. Der 316ti BMW, der in Ihrer Garage steht, ist ein Objekt dieser Klasse. Als objektorientierter Programmierer müssen Sie immer wie folgt vorgehen: Zuerst erstellen Sie die Klasse, dann basierend auf der Klasse das oder die benötigten Objekte. Ohne Klasse sprich ohne Objektbeschreibung können Sie logischerweise kein Objekt erstellen. Das Tolle an der Objektorientierung ist also, dass Sie Objekte aus der Wirklichkeit in Ihr Programm mithinübernehmen können. Anstatt sich mit der Hardware herumzuschlagen und das Spiel nach den Regeln des Computers zu spielen arbeiten Sie einfach innerhalb der Software mit den gleichen Objekten, die Ihnen in der Problemlösung im Kopf rumschwirren. Die Objektorientierung ist ein Meilenstein verglichen mit der prozeduralen Programmierung. Sie haben es vielleicht schon vermutet: So einfach wie sich alles anhört ist es jedoch in der Praxis nicht. Auch wenn die Objektorientierung viele Probleme löst, so schafft sie auch neue. Als objektorientierter Programmierer stehen Sie vor verschiedenen Problemen: Welche Objekte brauche ich tatsächlich zur Lösung einer Aufgabenstellung? Und welche Eigenschaften und Methoden brauche ich tatsächlich in einem Objekt, um es sinnvoll anwenden zu können? Wenn Sie sich nochmal die Software für den Bankautomaten vergegenwärtigen: Reichen als Objekte Kunde und Bank wirklich aus? Oder sollten nicht zusätzliche Objekte wie
  • 4. Benutzerschnittstelle, Geldbetrag, Kontostand, Geldkarte und so weiter verwendet werden? Damit könnten die Objekte Kunde und Bank etwas verkleinert werden, indem Informationen in anderen Objekten gespeichert werden. Während die Objekte übersichtlicher werden, wächst jedoch die Anzahl der Objekte im Programm insgesamt, was irgendwann auch unübersichtlich wird. Während der Kunde keine Eigenschaft Haarfarbe benötigt, hatten wir ihm eine Eigenschaft PIN spendiert. Welche Eigenschaften sind noch wichtig? Kontostand, Limit zum Überziehen des Kontos, Gültigkeitsdatum der Karte? Das Herausarbeiten der notwendigen Objekte und Festlegen von Eigenschaften und Fähigkeiten kann zum Teil enorm schwierig sein. Es können auch mehrere Lösungen gefunden werden, bei denen am Anfang kaum abzusehen ist, welche die beste ist. Das Herausarbeiten der richtigen Objekte, Eigenschaften und Fähigkeiten und die Konstruktion der Zusammenhänge, um letztendlich zu einem sinnvollen Programm zu gelangen, hat eine eigene Softwareindustrie geschaffen. Programme, die Entwicklern helfen, sinnvolle Objektmodelle zu erstellen und zu pflegen, sind vor allem in größeren Projektvorhaben immens wichtig und können vierstellige Beträge kosten. Die Objektorientierung hat neben dem ganz entscheidenden Vorteil der Abbildung von Objekten noch andere Stärken. • Perfekte Klassen kapseln Daten. Andere Klassen können also nie direkt auf eigene Daten zugreifen. Die Interaktion zwischen Objekten, die auf Klassen basieren, geschieht nicht über Datenzugriffe, sondern über den Zugriff auf Fähigkeiten. Der Kunde in unserem Beispiel ruft die Fähigkeit Kontostand verringern der Klasse Bank auf anstatt selber den Kontostand neu zu berechnen. Das ist allein Aufgabe der Klasse Bank, und keine andere Klasse sollte in dessen Daten reinpfuschen. Die objektorientierte Programmiersprache Smalltalk zwingt den Entwickler zum Erstellen perfekter Objekte, in denen alle Daten gekapselt sind, weil direkte Datenzugriffe nicht unterstützt werden. In C++ entscheidet der Programmierer mit Hilfe sogenannter Zugriffsattribute selbst, ob er das Konzept der Datenkapselung verfolgt oder nicht. • Klassen vererben Eigenschaften und Fähigkeiten an andere Klassen. Durch Vererbung können Klassenhierarchien erstellt werden, in denen jede Klasse von einer anderen Klasse erbt und an der Spitze der Klassenhierarchie eine oder mehrere Elternklassen stehen. Vererbung hat den Vorteil, dass Klassen austauschbar werden, weil sie eine gemeinsame Schnittstelle besitzen, wenn sie von der gleichen Elternklasse abstammen. C++ unterstützt im Gegensatz zu Java die Mehrfachvererbung: Eine Klasse kann mehr als eine Elternklasse haben und somit mehrere Schnittstellen erben. Im Kapitel 3, Vererbung lernen Sie die Vererbung genauer kennen. • Die Programmiersprache C++ ist keine 100%ig objektorientierte Programmiersprache. Sie können auch C++-Programme erstellen, in denen keine einzige Klasse und kein einziges Objekt vorkommt. Sie können mehr oder weniger beliebig die Regeln der Objektorientierung außer Kraft setzen. Wenn Ihnen etwas nicht passt, wie es in der Objektorientierung vorgesehen ist, dann müssen Sie es in C+ + höchstwahrscheinlich auch nicht so machen. Die Programmiersprache Smalltalk ist
  • 5. hier viel rigoroser: Entweder Sie halten sich an die Regeln oder Sie wechseln die Programmiersprache. Die extrem hohe Flexibilität von C++ ist wohl der wichtigste Grund, warum diese Programmiersprache den größten Marktanteil und die größte Beliebtheit unter den objektorientierten Sprachen besitzt. In C++ können Sie, müssen aber nicht alle Sprachmerkmale verwenden, die für eine objektorientierte Entwicklung zur Verfügung stehen. Das führt bei C++-Anfängern leicht zur Verwirrung: Alles scheint irgendwie optional zu sein und auch anders zu gehen. Hier hilft nur Üben, Üben, Üben. Je mehr Programme Sie in C++ erstellen, umso schneller erkennen Sie Vor- und Nachteile der verschiedenen Ansätze. Erfahrung ist, wie bei allen Programmiersprachen, auch in C++ das Wichtigste. 1.3 Klassen entwickeln. Schlüsselwörter und ihre Bedeutung Wie Sie bereits wissen, muss, bevor ein Objekt erstellt werden kann, erst eine Klasse entwickelt werden. Ob Sie die Klasse selber programmieren oder ob sie von jemand anderem entwickelt wurde und Sie sie beispielsweise aus dem offiziellen C++-Standard übernehmen spielt keine Rolle - Hauptsache, sie ist da. In C++ werden Klassendefinitionen normalerweise in Header-Dateien gepackt. Diese Dateien erhalten der Übersicht wegen normalerweise den gleichen Namen wie die Klasse. So können Sie beispielsweise davon ausgehen, dass in einer Header-Datei kunde.h eine Klasse kunde liegt und in bank.h eine Klasse bank. Wann immer Sie nun Objekte basierend auf der Klasse kunde oder der Klasse bank erstellen wollen, fügen Sie einfach über den Präprozessor- Befehl #include die Header-Datei in die Quellcode-Datei ein - und schon können Sie die Klasse verwenden, um darauf basierend ein Objekt zu erstellen. Wie sieht jedoch eine Klassendefinition aus? Sie wissen, dass eine Klasse Eigenschaften und Fähigkeiten festlegt. Wie definiert man das jedoch in C++? #include <string> class kunde { public: void PIN_eingeben(); private: std::string PIN; }; Was Sie oben sehen ist eine Klassendefinition. Klassendefinitionen beginnen entweder mit dem Schlüsselwort class oder struct. Den genauen Unterschied zwischen diesen beiden Schlüsselwörtern werden Sie später kennenlernen. Hinter dem Schlüsselwort wird der Name der Klasse angegeben. Obige Klasse heißt also kunde. Hinter dem Namen der Klasse folgen zwei geschweifte Klammern, zwischen denen die Definition der Klasse steht. Vergessen Sie nicht, hinter die geschlossene geschweifte Klammer ein Semikolon zu setzen - sonst meckert der Compiler.
  • 6. Obige Klasse besitzt eine Eigenschaft PIN und eine Fähigkeit, die PIN_eingeben() heißt. In der objektorientierten Terminologie spricht man bei PIN auch tatsächlich von einer Eigenschaft. Fähigkeiten werden jedoch Methoden genannt. In technischer Hinsicht ist eine Eigenschaft nichts anderes als eine Variable. Es spielt auch keine Rolle, ob die Variable einen intrinsischen Datentyp besitzt oder nicht. Eine Variable, die innerhalb der geschweiften Klammern einer Klasse definiert ist, wird Eigenschaft genannt. Methoden sind technisch nichts anderes als Funktionen. Funktionen, die innerhalb einer Klasse definiert sind, heißen Methoden. So können auch objektorientierte Programmierer ganz klar sagen, was sie meinen: Eine freistehende Funktion oder eine Funktion, die in einer Klasse definiert ist. Wenn Sie sich obige Klassendefinition ansehen, stellen Sie fest, dass die Methodendefinition nicht vollständig ist. Es ist schließlich nur der Methodenkopf angegeben. Was die Methode bei einem Aufruf eigentlich machen soll, steht nirgendwo. Die Klasse ist daher noch nicht ausreichend definiert und kann so wie oben auch nicht eingesetzt werden. Die Implementation von Methoden wird normalerweise von der Klassendefinition getrennt. Wenn eine Klasse kunde heißt, wird sie normalerweise in einer Datei kunde.h definiert. Die Methodendefinitionen befinden sich dann normalerweise in einer Datei kunde.cpp. So können Klasse und Dateien schnell zugeordnet werden. #include "kunde.h" void kunde::PIN_eingeben() { } Der Inhalt der Datei kunde.cpp, um die Klasse kunde zu vervollständigen, könnte wie oben aussehen. Die Klasse definiert eine einzige Methode PIN_eingeben(). Der Methodenkopf muss angegeben werden gefolgt von zwei geschweiften Klammern - also genauso wie wenn Sie eine freistehende Funktion definieren würden. Der einzige Unterschied: Nachdem es sich um eine Methode handelt, die ja immer einer Klasse zugeordnet ist, müssen Sie den Klassennamen gefolgt vom Zugriffsoperator :: vor den Methodennamen stellen. Wenn Sie das nicht machen, würde es sich bei PIN_eingeben() um eine freistehende Funktion handeln, die nicht der Klasse kunde zugeordnet ist. Damit wäre die Klasse kunde immer noch nicht vollständig. Anstatt die Implementation einer Methode von der Klasse, in der die Methode deklariert ist, zu trennen, können Sie auch folgendes schreiben. #include <string> class kunde { public: void PIN_eingeben() { }
  • 7. private: std::string PIN; }; Nun wird die Methode direkt innerhalb der Klasse kunde definiert und nicht mehr nur wie vorher deklariert. Es gibt einen minimalen Unterschied zwischen Methoden, die in einer Klasse nur deklariert und in einer Klasse vollständig definiert sind. Methoden, deren Implementation innerhalb einer Klasse liegt, heißen Inline-Methoden. Bei einem Aufruf einer Inline-Methode wird nicht der Code angesprungen, sondern der Compiler kopiert den Code der Methode jeweils an die Stellen der ausführbaren Datei, an denen die Methode verwendet wird. Inline-Methoden tauschen Speicherplatz gegen Geschwindigkeit ein: Es sind keine Sprünge nötig, um Code auszuführen. Dafür liegt der gleiche Code mehrfach in der ausführbaren Datei vor, so dass sich der Speicherbedarf der Anwendung erhöht. Sie können Inline-Methoden auch dann erstellen, wenn sich die Implementation einer Methode außerhalb der Klasse befindet. Sie müssen dann der Methodendeklaration in der Klasse das Schlüsselwort inline voranstellen. #include <string> class kunde { public: inline void PIN_eingeben(); private: std::string PIN; }; Die Methode PIN_eingeben() ist in der Klasse zwar nur deklariert und nicht definiert. Dennoch wird der Compiler den Code der Methode an all die Stellen in der ausführbaren Datei kopieren, an denen die Methode aufgerufen wird - jedenfalls in der Theorie. In der Praxis verstehen Compiler Inline-Methoden eher als Empfehlung und nicht als verbindliche Vorgabe. Der Grund ist, dass Compiler normalerweise besser beurteilen können, wie Code optimiert werden soll - unabhängig davon, ob Inline-Methoden verwendet werden oder nicht. In der Praxis werden für gewöhnlich Klassendefinition und Methodendefinitionen immer in getrennte Dateien gelegt. Selbst für Inline-Methoden wird eher das Schlüsselwort inline verwendet als dass die Methode innerhalb der Klasse komplett definiert wird. Der Vorteil dieser Aufteilung ist, dass Sie anhand einer Klasse die Eigenschaften und Methoden ablesen können, ohne dass Sie sich mit der Implementation der Methoden rumschlagen müssen. Die Implementation interessiert Sie normalerweise nicht, wenn Sie Methoden für ein Objekt aufrufen möchten. Die Implementation ist ja Aufgabe der Klasse. Sie müssen nur wissen, welche Eigenschaften und Methoden die Klasse zur Verfügung stellt, um mit ihr arbeiten zu können. Eine Klassendefinition ist also in diesem Fall eine Art Dokumentation für Programmierer, die Aufschluss darüber gibt, welche Schnittstelle zur Verfügung steht.
  • 8. 1.4 Objekte anlegen. Klassen zum Leben erwecken Wenn Sie eine Klasse definiert haben, haben Sie den ersten Schritt getan. Der zweite Schritt besteht nun darin, auf die Klasse zuzugreifen und ein Objekt basierend auf der Klasse zu erstellen. Objekte anlegen ist extrem einfach. Es handelt sich hierbei schlichtweg um Variablen, deren Datentyp eine Klasse ist. Das ist die Definition eines Objekts. Um also ein Objekt zu erstellen, gehen Sie so wie immer vor, wenn Sie eine Variable anlegen. Sie geben zuerst den Datentyp an und dann den Namen der Variablen, in diesem Fall eben den Namen des Objekts. #include "kunde.h" kunde k; Damit Sie ein Objekt vom Datentyp kunde erstellen können, müssen Sie den Datentyp selbstverständlich erst bekanntmachen. Wenn Sie die Klasse in der Header-Datei kunde.h definiert haben, fügen Sie diese einfach über den Präprozessorbefehl #include in Ihre aktuelle Quellcode-Datei ein. Im obigen Beispiel wird also eine Variable k definiert, die genaugenommen ein Objekt darstellt, und zwar vom Datentyp der Klasse kunde. In der Klasse kunde haben Sie angegeben gehabt, dass es eine Methode PIN_eingeben() gibt. Ihr Objekt besitzt also die Fähigkeit, eine PIN eingeben zu können. Wie greifen Sie innerhalb von C++ auf diese Fähigkeit Ihres Objekts k zu? Auf Eigenschaften und Methoden von Objekten wird über den Zugriffsoperator . zugegriffen. Um also die Methode PIN_eingeben() für Ihr Objekt k aufzurufen, geben Sie folgende Zeile an. k.PIN_eingeben(); Diese Zeile ist letztendlich nichts anderes als der Aufruf einer Funktion - nur eben nicht einer freistehenden Funktion, sondern einer, die innerhalb des Datentyps definiert ist, auf dem das Objekt basiert, für das Sie die Funktion aufrufen. Das Objekt k basiert auf der Klasse kunde, und diese Klasse besitzt eine Methode namens PIN_eingeben(), deren Parameterliste leer ist. Obiger Methodenaufruf ist dementsprechend völlig korrekt und würde vom Compiler ohne Meckern übersetzt werden. Sie hatten ein paar Abschnitte zuvor einen anderen Zugriffsoperator kennengelernt, nämlich ::, um bei Methodendefinitionen angegeben zu können, zu welcher Klasse eine Methode überhaupt gehört. Damit Sie nicht durcheinanderkommen: :: ist der Zugriffsoperator für Klassen, . der Zugriffsoperator für Objekte. 1.5 Zugriffsrechte. Zugriff erlaubt oder nicht Sie wissen, dass Sie über den Zugriffsoperator . auf Eigenschaften und Methoden eines Objekts zugreifen können. Trotzdem würde der Compiler folgende Code-Zeile nicht übersetzen.
  • 9. k.PIN = "Abc"; Obwohl die Klasse kunde eine Eigenschaft PIN besitzt, können Sie nicht auf diese Eigenschaft zugreifen. Die Eigenschaft PIN ist nämlich privat. Die Programmiersprache C++ unterstützt zwei Zugriffsattribute: public und private. Auf Eigenschaften und Methoden, die hinter public angegeben sind, darf von außerhalb der Klasse zugegriffen werden. Auf Eigenschaften und Methoden, die hinter private angegeben sind, darf nicht von außerhalb der Klasse zugegriffen werden. Private Eigenschaften und Methoden sind also für die interne Verwendung in der Klasse gedacht. C++ unterstützt noch ein drittes Zugriffsattribut, was jedoch nur im Zusammenhang mit Vererbung von Bedeutung ist und daher erst in einem späteren Kapitel vorgestellt wird. Erinnern Sie sich noch daran, dass für eine Klassendefinition in C++ zwei Schlüsselwörter zur Verfügung stehen? Das eine Schlüsselwort, das in den allermeisten Fällen verwendet wird, haben Sie bereits kennengelernt - es ist class. Anstatt eine Klasse mit class zu definieren, können Sie auch das Schlüsselwort struct verwenden. Der einzige Unterschied zwischen class und struct: In einer mit class definierten Klasse sind Eigenschaften und Methoden standardmäßig privat, in einer mit struct definierten Klasse sind Eigenschaften und Methoden standardmäßig öffentlich. Nachdem Sie mit den Zugriffsattributen private und public jederzeit die Art des Zugriffs in einer Klasse festlegen können, können Sie Klassen auf unterschiedliche Weise definieren. class beispiel { int Eigenschaft1; int Eigenschaft2; public: void Methode1(); void Methode2(); }; Obige Klasse mit dem Namen beispiel definiert zwei private Eigenschaften und zwei öffentliche Methoden. Wenn Sie die Klasse anstatt mit class mit struct definieren möchten, schreiben Sie sie wie folgt. struct beispiel { void Methode1(); void Methode2(); private: int Eigenschaft1; int Eigenschaft2; }; Beide Klassendefinitionen sind gleich. Der Compiler generiert jeweils den gleichen Code. Auf welche Weise Sie Ihre Klassen definieren, spielt demnach keine Rolle. Es hat sich eingebürgert, normalerweise class zu verwenden. Sie sollten struct nur dann einsetzen, wenn Sie dokumentieren möchten, dass Ihre Klasse hauptsächlich aus öffentlichen
  • 10. Eigenschaften und Methoden besteht und daher anderen Klassen ein sehr weiträumiger Zugriff eingeräumt wird. Sie können die Zugriffsattribute public und private auch mehrfach in einer Klassendefinition verwenden. Sie sollten jedoch davon absehen und Eigenschaften und Methoden, die dem gleichen Zugriffsmechanismus unterliegen, in einem Block zusammenstellen, da dies die Übersicht erhöht. 1.6 Praxis-Beispiel. So geht's In diesem Abschnitt werden die immer mal wieder als Beispiel in diesem Kapitel angesprochenen Klassen kunde und bank verkomplettiert und in einer kleinen Anwendung verwendet. Diese Anwendung simuliert einen Bankautomaten, an dem Sie Geld abheben können. Der Kunde muss nicht mehr nur die Fähigkeit besitzen, eine PIN eingeben zu können, sondern er muss ebenfalls seine Geldkarte in den Automaten schieben und einen Betrag auswählen können. Die Klasse kunde wird daher erweitert, so dass sie wie folgt aussieht. #include <string> class kunde { public: void geldkarte_einschieben(); void PIN_eingeben(); void betrag_waehlen(); private: std::string PIN; }; Die Implementierung der Methoden wird wie üblich in einer anderen Datei vorgenommen. Die Methode PIN_eingeben() bekommt nun außerdem einen sinnvolleren Methodenrumpf verpasst, nachdem sie ja bisher keine Anweisungen enthalten hat und daher bei einem Aufruf nichts geschehen wäre. Die Methode geldkarte_einschieben() kann einen derartigen Vorgang natürlich nur simulieren. Sie haben höchstwahrscheinlich kein Kartenlesegerät an Ihren Computer angeschlossen. Die Programmierung von Kartenlesegeräten ist außerdem extrem kompliziert, nachdem Sie hier in völligem Gegensatz zur Objektorientierung sehr hardwarenah programmieren müssen. Unsere Methode geldkarte_einschieben() simuliert den Vorgang dadurch, dass Sie einfach einen Benutzernamen eingeben müssen. #include "kunde.h" #include <iostream> #include <string> void kunde::geldkarte_einschieben() { std::string Benutzername; std::cout << "Schieben Sie bitte Ihre Karte in den Automaten: " << std::flush;
  • 11. std::cin >> Benutzername; } void kunde::PIN_eingeben() { std::cout << "Geben Sie Ihre PIN ein: " << std::flush; std::cin >> PIN; } void kunde::betrag_waehlen() { int Betrag; std::cout << "Geben Sie ein, wieviel Geld Sie abheben moechten: " << std::flush; std::cin >> Betrag; } In den drei Methoden wird jeweils auf die Standardein- und -ausgabe zugegriffen, so dass die Header-Datei iostream eingebunden werden muss. Die Methode geldkarte_einschieben() legt ein Objekt vom Typ std::string an. Daher muss außerdem die Header-Datei string mit #include eingebunden werden. Alle drei Methoden geben einen Text auf die Standardausgabe aus und erwarten eine Eingabe vom Anwender. Sehen Sie sich die Methode PIN_eingeben() genau an. Es werden Daten von der Standardeingabe eingelesen und in einer Variablen PIN gespeichert, die gar nicht in der Methode definiert ist. Der Compiler meckert trotzdem nicht. PIN ist eine Eigenschaft der Klasse kunde und dort definiert. Jede Methode einer Klasse kann jederzeit auf Eigenschaften in einer Klasse zugreifen. In diesem Fall wird also die Eingabe des Anwenders in einer Eigenschaft gespeichert und nicht in einer lokalen Variable. Übrigens: Die Eigenschaft PIN ist eine private Eigenschaft. Zugriffsattribute wie private und public schränken den Zugriff auf Eigenschaften und Methoden nur gegenüber anderen Klassen ein. Eine Methode in einer Klasse kann grundsätzlich auf alle Eigenschaften und Methoden zugreifen, völlig egal, mit welchen Zugriffsattributen sie geschützt sind. Zugriffsattribute schränken nur den Zugriff von außen ein. Der Vorteil von Eigenschaften ist, dass sie einen größeren Gültigkeitsbereich haben als lokale Variablen. Die Eigenschaft PIN existiert genauso lange wie das Objekt, das auf der Klasse kunde basiert. Wenn der Anwender eine PIN eingegeben hat und die Methode PIN_eingeben() beendet wurde, ist die Eingabe des Anwenders immer noch in der Eigenschaft PIN gespeichert. Dies ist bei den Methoden geldkarte_einschieben() und betrag_waehlen() nicht der Fall: Dort werden Eingaben des Anwenders in lokalen Variablen gespeichert, die nach Ende der Methode aus dem Speicher gelöscht werden. Ihr Gültigkeitsbereich erstreckt sich lediglich über die Methoden und nicht weiter. Die Methoden geldkarte_einschieben() und betrag_waehlen() müssen später nachbearbeitet werden, wenn feststeht, wie die Klasse kunde und deren Methoden mit der Klasse bank zusammenarbeiten. Im nächsten Schritt wird daher die Klasse bank definiert. Die Klasse bank muss Daten zum Konto verwalten, damit zum einen überprüft werden kann, ob der Zugang zum Konto durch
  • 12. den Kunden am Bankautomaten in Ordnung geht, und zum anderen verhindert werden kann, dass der Kunde unendlich viel Geld abhebt. Die Klasse bank wird daher in einem ersten Schritt wie folgt definiert. #include <string> class bank { private: std::string Benutzername; std::string PIN; int Kontostand; }; Welche Fähigkeiten müssen der Bank spendiert werden? Sie muss überprüfen, ob der vom Kunden eingegebene Benutzername und die PIN zusammenpassen und der Zugang gewährleistet wird. Sie muss außerdem bei einer Bargeldabhebung den Kontostand verringern und gegebenenfalls die Auszahlung verhindern, falls das Konto überzogen wird. Die Klasse bank wird daher wie folgt erweitert. #include <string> class bank { public: bool zugriff_ueberpruefen(std::string benutzername, std::string pin); bool geld_abheben(int betrag); private: std::string Benutzername; std::string PIN; int Kontostand; }; Die Klasse bank erhält zwei Methoden zugriff_ueberpruefen() und geld_abheben(). Beide Methoden geben einen Wahrheitswert zurück, der angibt, ob der Zugriff in Ordnung geht bzw. ob das Geld abgehoben werden konnte. Um den Zugriff überprüfen zu können, werden der Methode zugriff_ueberpruefen() beim Aufruf zwei Werte übergeben - nämlich der Benutzername und die PIN, die der Anwender eingegeben hat. Der Methode geld_abheben() wird ein Parameter vom Typ int übergeben, der den Betrag angibt, den der Kunde abheben möchte. Was noch fehlt ist eine Möglichkeit, die Eigenschaften der Klasse bank zu initialisieren. Deswegen wird der Klasse bank eine Methode init() spendiert, die ganz am Anfang des Programms aufgerufen werden muss und festlegt, mit welchen Werten die Eigenschaften Benutzername, PIN und Kontostand vorbelegt werden. #include <string> class bank { public: void init(std::string benutzername, std::string pin, int kontostand); bool zugriff_ueberpruefen(std::string benutzername, std::string pin);
  • 13. bool geld_abheben(int betrag); private: std::string Benutzername; std::string PIN; int Kontostand; }; Nun fehlt noch die Implementierung der Methoden. #include "bank.h" void bank::init(std::string benutzername, std::string pin, int kontostand) { Benutzername = benutzername; PIN = pin; Kontostand = kontostand; } bool bank::zugriff_ueberpruefen(std::string benutzername, std::string pin) { if (Benutzername == benutzername && PIN == pin) { return true; } return false; } bool bank::geld_abheben(int betrag) { if (Kontostand >= betrag) { Kontostand -= betrag; return true; } return false; } Die Methode init() setzt lediglich die Eigenschaften auf die Werte, die als Parameter übergeben werden. Die Methode zugriff_ueberpruefen() vergleicht den als Parameter übergebenen Benutzernamen und die PIN mit den Eigenschaften des Objekts und gibt true oder false zurück. In der Methode geld_abheben() wird zuerst überprüft, ob der Betrag, den der Kunde abheben möchte, nicht den aktuellen Kontostand übersteigt. Ist dies nicht der Fall, wird der Kontostand neuberechnet und true zurückgegeben - andernfalls false. Die Klasse bank ist somit fertig. Wir müssen uns nun wieder der Klasse kunde zuwenden und sie vervollständigen bzw. den Zugriff auf die Bank hinzufügen. Die Klasse kunde muss hierzu ein wenig umgebaut werden. Die Eingabe des Benutzernamens, der ja die Geldkarte simuliert, muss in einer Eigenschaft in der Klasse gespeichert werden. Andernfalls kann in der Methode PIN_eingeben() die Bank gar nicht den Zugriff überprüfen, wenn der eingegebene Benutzername nirgendwo dauerhaft gespeichert wird.
  • 14. Die Methde PIN_eingeben() soll außerdem zurückgeben, ob die Bank den Zugriff gestattet oder nicht. Ist der Zugriff nämlich nicht gestattet, muss der Anwender seine Karte entnehmen und sie neu einlegen. Im Programm muss also der Benutzername neu eingegeben werden. Es darf nicht sein, dass der Kunde eine beliebige PIN eingibt, die Bank den Zugriff nicht gestattet, der Kunde dann trotzdem Geld abheben kann. Die Methode betrag_waehlen() soll ebenfalls zurückgeben, ob die Auszahlung erfolgreich war oder nicht. Die Definition der Klasse kunde ändert sich minimal. Lediglich Benutzername wird als neue Eigenschaft hinzugefügt, und der Rückgabewert der Methoden PIN_eingeben() und betrag_waehlen() wird angepasst. #include <string> class kunde { public: void geldkarte_einschieben(); bool PIN_eingeben(); bool betrag_waehlen(); private: std::string Benutzername; std::string PIN; }; In die Implementierung der Methoden der Klasse kunde wird tiefergehend eingegriffen. #include "kunde.h" #include "bank.h" #include <iostream> bank b; void kunde::geldkarte_einschieben() { std::cout << "Schieben Sie bitte Ihre Karte in den Automaten: " << std::flush; std::cin >> Benutzername; } bool kunde::PIN_eingeben() { std::cout << "Geben Sie Ihre PIN ein: " << std::flush; std::cin >> PIN; return b.zugriff_ueberpruefen(Benutzername, PIN); } bool kunde::betrag_waehlen() { int Betrag; std::cout << "Geben Sie ein, wieviel Geld Sie abheben moechten: " << std::flush; std::cin >> Betrag; return b.geld_abheben(Betrag); }
  • 15. Beachten Sie zuallererst, dass in dieser Datei ein globales Objekt b vom Typ bank angelegt wird. Zu diesem Zweck wird außerdem die Header-Datei bank.h eingebunden, um die Klasse bekanntzumachen. Die Methode geldkarte_einschieben() speichert den Benutzernamen nun nicht mehr in einer lokalen Variablen, sondern in einer Eigenschaft. In der Methode PIN_eingeben() wird dieser Benutzername zusammen mit der PIN an die Methode zugriff_ueberpruefen() des Objekts b weitergegeben. Der Rückgabewert dieser Methode ist gleichzeitig der Rückgabewert der Methode PIN_eingeben(). In der Methode betrag_waehlen() wird ebenfalls auf das Objekt b zugegriffen. Der Methode geld_abheben() wird der vom Anwender eingegebene Geldbetrag übergeben, der abgehoben werden soll. Der Rückgabewert dieser Methode ist wieder gleichzeitig der Rückgabewert der Methode betrag_waehlen(). Das einzige, was noch fehlt, ist die Funktion main(), um das Programm starten zu können. Die Funktion sieht wie folgt aus. #include "kunde.h" #include "bank.h" #include <iostream> extern bank b; int main() { kunde k; b.init("boris", "1234", 1000); for (;;) { k.geldkarte_einschieben(); if (k.PIN_eingeben() == true) { if (k.betrag_waehlen() == true) { std::cout << "Der gewuenschte Betrag wurde abgehoben." << std::endl; } } else { std::cout << "Die PIN ist falsch." << std::endl; } } } In der Funktion main() wird ein Objekt vom Typ kunde angelegt. Danach wird das Objekt b initialisiert, indem die Methode init() aufgerufen wird. Beachten Sie, wie auf das Objekt zugegriffen wird. Es wird vor der Funktion main() mit dem Schlüsselwort extern bekanntgemacht. Dies bedeutet, dass innerhalb dieser Datei auf ein Objekt b zugegriffen werden kann, das in einer anderen Datei angelegt wird. Sehen Sie sich kunde.cpp an: In der Datei, in der die Methoden der Klasse kunde definiert sind, wird ein Objekt b erstellt. Auf
  • 16. dieses Objekt wird nun in der Funktion main() zugegriffen, um es zu initialisieren. Würden Sie das Schlüsselwort extern weglassen, würden Sie ein neues Objekt namens b anlegen. Der Compiler würde daraufhin den Code nicht übersetzen, da es zwei gleichnamige Objekte im gleichen Gültigkeitsbereich geben würde. Sie müssen daher extern angeben. Nachdem das Objekt b initialisiert wurde, wird eine Endlosschleife mit for gestartet. Wenn Sie das C++-Programm starten, können Sie es ausschließlich mit der Tastenkombination Strg+C abbrechen. Nachdem ein Bankautomat für gewöhnlich auch nicht beendet oder heruntergefahren wird, ist die Endlosschleife in diesem Fall in Ordnung. In der Endlosschleife wird auf das Objekt k zugegriffen. Es werden nacheinander die drei Methoden aufgerufen, die für dieses Objekt definiert sind. Für die Methoden PIN_eingeben() und betrag_waehlen() wird jedoch der Rückgabewert überprüft. Denn daran erkennt das Programm, ob der Zugriff auf das Bankkonto gestattet ist und der eingegebene Betrag abgehoben werden konnte. Wird eine falsche PIN eingegeben, wird der Kunde erst gar nicht aufgefordert, einen Betrag zu wählen. Stimmt die PIN und der Kunde versucht, mehr Geld abzuheben als auf dem Konto liegt, erfolgt die Abbuchung nicht. Der Bankautomat zeigt in diesem Fall auch keine entsprechende Bestätigung des Abbuchungsvorgangs an. Das Programm ist nun fertig. Sie können es starten und ausprobieren. Geben Sie als Benutzernamen boris und als PIN 1234 ein, um Zugriff auf das Bankkonto zu erhalten. Von dort können Sie insgesamt 1000 Euro abheben. Dies sind die Werte, mit denen die Bank in init() initialisiert wurde. Copyright © 2001-2010 Boris Schäling