C++: Fortgeschrittene Syntax

Inhaltsverzeichnis und Lernziele des Kapitels C++: Fortgeschrittene Syntax.
Noch keine Stimmen abgegeben
Noch keine Kommentare

Einordnung des Artikels

Inhaltsverzeichnis

  1. C++: Strukturierte Programmierung mit Funktionen
  2. Weitere Konzepte der strukturierten Programmierung in C++: Einsatz von Vektoren, G├╝ltigkeitsbereiche
  3. Spezielle Konzepte der strukturierten Programmierung in C++: call by reference, Rekursion, Function Templates
  4. C++: Aufgaben zur strukturierten Programmierung
  5. C++: Grundlagen der objektorientierten Programmierung (OOP)
  6. C++: Konstruktoren und Destruktoren
  7. Objekt-orientiertes Design in C++: Datenkapselung und UML-Diagramme
  8. Objekt-orientiertes Design in C++: Komposition und Vererbung

Lernziele

In dieser Einf├╝hrung in die Informatik sind zwei Teile zu C++ enthalten: die Einf├╝hrung in C++ und C++: Fortgeschrittene Syntax. Im Teil Einf├╝hrung in C++ wurde die elementare Syntax von C++ vorgestellt, insbesondere wie die allgegenw├Ąrtigen Strukturelemente Bedingung, Alternative und Schleife in C++ formuliert werden. Damit lassen sich bereits beliebige Algorithmen implementieren, man arbeitet dabei allerdings auf der Ebene der prozeduralen Programmierung. Das hei├čt, man schreibt einen Algorithmus als Abfolge von Befehlen und kann noch keine Unterprogramme bilden. Diese Art der Programmierung ist f├╝r kleine Programme, deren Quelltexte etwa ein bis zwei Bildschirme f├╝llen, v├Âllig ausreichend. Gr├Â├čere Projekte sollte man mit dieser Technik aber nicht in Angriff nehmen.

Deshalb werden in diesem Teil C++: Fortgeschrittene Syntax diejenigen Konzepte vorgestellt, die man f├╝r beliebig gro├če Projekte ben├Âtigt. Damit sind insbesondere Funktionen (oder Unterprogramme) gemeint, um im Sinne der strukturierten Programmierung zu arbeiten, sowie Klassen, um objekt-orientierte Programmierung (OOP) zu verwirklichen.

Es wird sich zeigen, dass in diesem Umkreis noch weitere Konzepte vorgestellt werden m├╝ssen, die man f├╝r einen sicheren Umgang mit strukturierter beziehungsweise objekt-orientierter Programmierung ben├Âtigt; um die wichtigsten Konzepte zu nennen:

  • der Unterschied zwischen call by value und call by reference
  • Vertiefung des Begriffes des G├╝ltigkeitsbereiches (scope)
  • Function Templates
  • Container-Klassen aus der Standard-Bibliothek, insbesondere Vektoren (vector) und Felder (array)
  • Konstruktoren und Destruktoren
  • Datenkapselung
  • UML-Diagramme
  • Vererbung, Komposition
  • polymorphe Funktionen.

Nach dem Durcharbeiten dieses Teils sollten Sie in der Lage sein:

  • die Eigenschaften der strukturierten und objekt-orientierten Programmierung kennen (so wie sie auf abstrakter Ebene im Teil Einf├╝hrung in die Programmierung beschrieben wurden),
  • die entsprechenden Konzepte konkret mit der Sprache C++ anwenden k├Ânnen,
  • und damit Aufgaben l├Âsen, wie sie im Teil Programmieraufgaben vorgestellt werden.

C++: Strukturierte Programmierung mit Funktionen

In der strukturierten Programmierung versucht man Aufgaben, die immer wieder erledigt werden m├╝ssen, in Funktionen (oder Unterprogramme) auszulagern. Dadurch wird das Hauptprogramm schlanker und ÔÇö bei geeigneter Wahl der Namen der Funktionen ÔÇö liest es sich so leicht wie Pseudocode.

In diesem ersten Kapitel lernen Sie die Syntax kennen, wie in C++ Funktionen realisiert werden und mit Hilfe der ersten Beispiele werden schon die ersten Design-Prinzipien vorgestellt. Nach dem Durcharbeiten dieses Kapitels sollten Sie:

  • Die Unterscheidung zwischen Deklaration und Implementierung einer Funktion kennen und f├╝r beide die Syntax beherrschen.
  • Sie sollten verstanden haben, warum man diese Trennung vornimmt und welche Informationen in der Deklaration beziehungsweise Implementierung enthalten ist.
  • Verstehen, warum man fr├╝her zwischen Prozedur und Funktion unterschieden hat und warum diese Trennung heute nicht mehr vorgenommen wird und man nur noch von Funktionen spricht (die Aktionen ausf├╝hren oder einen R├╝ckgabewert berechnen ÔÇö hier wird oder wie ein logisches ODER verwendet und es sind auch Speizialf├Ąlle denkbar f├╝r Funktionen, die entweder Aktionen ausf├╝hren oder nur einen R├╝ckgabewert berechnen).
  • Sie sollen wissen,
    • was man unter dem ├ťberladen einer Funktion versteht,
    • welche Versionen des ├ťberladens m├Âglich sind und welche nicht,
    • wann das ├ťberladen einer Funktion sinnvoll eingesetzt werden kann und
    • wie man das ├ťberladen von Funktionen in C++ realisiert.
  • Verbunden damit sind die Begriffe Prototyp einer Funktion und Signatur einer Funktion; Sie sollten diese Begriffe kennen, da sie in der Literatur sehr oft verwendet werden und genauer beschreiben, welche Information in der Deklaration enthalten ist.
  • Sie sollen globale Funktionen definieren k├Ânnen und verstehen, wie man die Deklaration und die Implementierung von Funktionen in verschiedenen Dateien vornimmt (Header-Datei mit der Endung .h und Implementierung mit der Endung .cpp).

Weitere Konzepte der strukturierten Programmierung in C++: Einsatz von Vektoren, G├╝ltigkeitsbereiche

In diesem Kapitel werden einige Beispiele f├╝r Funktionen vorgestellt, die von Feldern (array) und Vektoren (vector) Gebrauch machen. Diese werden eingesetzt, wenn man Listen von gleichartigen Objekten ben├Âtigt (zum Beispiel Listen von Gleitkommazahlen oder ganzen Zahlen). In einem Feld kann dabei die Anzahl der Objekte nicht mehr ver├Ąndert werden, wenn das Feld einmal erzeugt wurde, dagegen kann bei einem Vektor die Anzahl der Objekte auch sp├Ąter noch ver├Ąndert werden. Es sollte klar sein, dass diese Container-Klassen nach den fundamentalen Datentypen die wichtigsten Datentypen in C++ sind.

Und anhand der Beispiele f├╝r Funktionen werden die Konzepte G├╝ltigkeitsbereich einer Variable, lokale Variable, globale Variable und lokale static-Variable vorgestellt. Gerade bei gro├čen Projekten (wo es schnell vorkommen kann, dass Variablen gleichen Namen besitzen, aber g├Ąnzlich verschiedene Bedeutung haben), muss man darauf achten, dass der G├╝ltigkeitsbereich einer Variable so klein wie m├Âglich gemacht wird, um Namenskonflikte zu vermeiden. Dazu ist es n├Âtig, die genannten Arten von Variablen und ihre Eigenschaften zu kennen und zu verstehen, wann man welche einsetzen muss.

Spezielle Konzepte der strukturierten Programmierung in C++: call by reference, Rekursion, Function Templates

Die hier vorgestellten Konzepte sind f├╝r Anf├Ąnger schwer zu verstehen und Sie werden sie in Ihren ersten Programmen kaum einsetzen. Da sie aber in der Standard-Bibliothek h├Ąufig vorkommen und Sie im Lauf der Zeit mehr und mehr dazu ├╝bergehen, auf Funktionen und Klassen aus der Standard-Bibliothek zuzugreifen, ist es wichtig diese Konzepte kennenzulernen. Sp├Ątestens wenn Sie von Sandkastenspielen zu ernsthafter Programmierung ├╝bergehen, werden Sie diese Konzepte selbst einsetzen m├╝ssen.

C++: Aufgaben zur strukturierten Programmierung

Sie werden schnell sehen, dass ein Programm, in dem Funktionen definiert werden, nicht automatisch besser ist als das entsprechende Programm, das den kompletten Algorithmus als eine Abfolge von Befehlen ohne Funktionen implementiert. Man muss hier schwierige Design-Entscheidungen treffen, damit die strukturierte Programmierung tats├Ąchlich besser lesbare und schlankere Programme liefert:

  • Welche Aufgaben werden in Funktionen ausgelagert?
  • Wann soll eine Funktion in mehrere Funktionen zerlegt werden?
  • Welche Deklaration (also welche Datentypen f├╝r die Eingabe- und R├╝ckgabewerte) ist f├╝r eine Funktion geeignet? (Bei der objekt-orientierten Programmierung wird man diese Entscheidung nach anderen Kriterien vornehmen.)

Es ist daher unbedingt n├Âtig, dass Sie einige ├ťbungen absolvieren, bei denen Sie:

  • einerseits die Syntax f├╝r die Deklaration, Implementierung und den Aufruf von Funktionen ein├╝ben und
  • andererseits erste Design-Entscheidungen selber treffen m├╝ssen.

C++: Grundlagen der objekt-orientierten Programmierung (OOP)

In der ├ťbersicht ├╝ber Programmiersprachen wurden ÔÇö sehr allgemein ÔÇö die Eigenschaften und Vorteile einer objekt-orientierten Programmiersprache beschrieben. Grundlegend daf├╝r ist die Unterscheidung zwischen Klasse und Objekt. Eine Klasse wird oft als der Bauplan f├╝r ein Objekt bezeichnet: sie definiert die Datenelemente (Eigenschaften) und Methoden (Funktionalit├Ąten), wobei die Datenelemente in einem konkreten Objekt spezielle Werte annehmen.

Hier wird die C++-Syntax eingef├╝hrt, mit der die Konzepte der objekt-orientierten Programmierung umgesetzt werden. Lernziele sind dabei:

  • Sie sollen den Unterschied zwischen Klasse und Objekt beschreiben k├Ânnen.
  • Sie sollen Klassen in C++ anlegen k├Ânnen und dazu verstanden haben, wie man dabei (├Ąhnlich wie bei Funktionen) zwischen Deklaration und Implementierung trennt.
  • Sie sollen sich mit Ihrer Entwicklungsumgebung vertraut machen, um zu wissen, wie Sie von ihr beim Anlegen einer neuen Klasse unterst├╝tzt werden.
  • Die vorgestellten Beispiele sollen verdeutlichen, dass die objekt-orientierte Programmierung erst bei gr├Â├čeren Projekten eingesetzt wird. Deren Umfang ist jetzt deutlich gr├Â├čer als bei den Beispielen zur strukturierten Programmierung und daher ist es wichtig, sich vor dem Anlegen der Klasse einen objekt-orientierten Entwurf zu ├╝berlegen. Sp├Ąter werden Sie noch weitere Elemente kennenlernen, die in einen Entwurf eingehen k├Ânnen.

Damit ist klar, dass auch hier wichtige Design-Entscheidungen zu treffen sind:

  • Wie werden die Verantwortlichkeiten in einem umfangreichen Programm auf die einzelnen Klassen verteilt?
  • Welche Datenelemente und Methoden erh├Ąlt eine Klasse?
  • Welche Datentypen sind f├╝r die Datenelemente geeignet?
  • Welche Deklarationen sind f├╝r die Methoden geeignet?

Um diese Entscheidungen zu treffen, werden in den folgenden Abschnitten weitere Konzepte der objekt-orientierten Programmierung vorgestellt.

C++: Konstruktoren und Destruktoren

Die Aktionen, die beim Erzeugen eines Objektes einer Klasse ausgef├╝hrt werden m├╝ssen (Initialisierung von Variablen, Erzeugen anderer Objekte), werden im Konstruktor der Klasse zusammengefasst. Entsprechend enth├Ąlt der Destruktor die Aktionen, die ausgef├╝hrt werden bevor das Objekt zerst├Ârt wird (also aus dem Hauptspeicher entfernt wird).

Wie andere Funktionen kann ein Konstruktor ├╝berladen werden. Daher ist es wichtig in einem objekt-orientierten Entwurf festzulegen, welche Konstruktoren mit welchen Eingabewerten angeboten werden. Dazu wird das Design-Muster der Delegation vorgestellt, das man sehr geschickt einsetzen kann, um Quelltexte schlanker und leichter wartbar zu gestalten.

Wird kein Konstruktor explizit definiert, besitzt jede Klasse einen sogenannten Standard-Konstruktor (default-Konstruktor); mit ihm sind einige Spitzfindigkeiten verbunden, die man als Programmierer kennen muss.

In vielen Anwendungen wird ein sogenannter Kopier-Konstruktor ben├Âtigt: mit ihm kann festgelegt werden, welche Aktionen beim Kopieren eines Objektes ausgef├╝hrt werden.

Nach dem Durcharbeiten dieses Kapitels sollen Sie die hier vorgestellten Konstruktoren (und den Destruktor) und ihre Eigenschaften kennen, um selber Design-Entscheidungen zu treffen, wann und wie sie eingesetzt werden.

Objekt-orientiertes Design in C++: Datenkapselung und UML-Diagramme

Weitere Design-Entscheidungen betreffen die sogenannte Zugriffs-Spezifikation (access modifier). Damit ist gemeint, dass man Methoden einer Klasse als ├Âffentlich (public) oder privat (private) kennzeichnen kann, wodurch festgelegt wird, ob die Methoden von anderen Klassen aufgerufen werden k├Ânnen oder nicht.

Diese Unterscheidung h├Ârt sich zun├Ąchst eher belanglos an, ist aber bei gro├čen Projekten wieder eine wichtige Design-Entscheidung: die ├Âffentlichen Methoden legen fest, welche Aktionen das Programm nach au├čen sichtbar ausf├╝hren kann, dagegen sind die privaten Methoden eher Hilfs-Methoden, die die Implementierung komplexer Algorithmen erleichtern. Etwas abstrakter formuliert, kann damit eine Datenkapselung erreicht werden, da gewisse Teile des Programmes nach au├čen nicht sichtbar sind.

In diesem Abschnitt wird am Beispiel eines kleinen Statistik-Projektes (insbesondere beim Einbau eines Zufallsgenerators) diskutiert, welche Methoden als ├Âffentlich beziehungsweise als privat spezifiziert werden.

Bei der Besprechung von Design-Entscheidungen ist Ihnen inzwischen sicherlich aufgefallen, dass die Deklaration einer Methode viel wichtiger ist als ihre Implementierung. Die sogenannten UML-Klassendiagramme bieten eine M├Âglichkeit, die Deklarationen zusammen mit den Zugriffs-Spezifikationen ├╝bersichtlich und schnell verst├Ąndlich darzustellen. Sie sind daher ein unverzichtbares Hilfsmittel beim Entwurf von Klassen geworden.

Objekt-orientiertes Design in C++: Komposition und Vererbung

In diesem Abschnitt wird die objekt-orientierte Programmierung mit C++ zum Abschluss gebracht: Sie lernen, wie man die Vererbung in C++ realisiert. In den Beispielen wird dann gezeigt:

  • wie man die Vererbung einsetzen kann (insbesondere um bereits vorhandene Klassen ÔÇö sei es aus Bibliotheken oder selbst implementierte ÔÇö einzusetzen und zu erweitern),
  • wie man sie gleichwertig durch eine Komposition von Klassen ersetzen kann und
  • wie man durch die Kombination von Vererbung und Komposition eine Baumstruktur implementieren kann.

Letzteres soll insbesondere als Beispiel f├╝r eine selbstdefinierte Datenstruktur dienen ÔÇö und Ihnen aufzeigen, welche ungeahnten M├Âglichkeiten die objekt-orientierte Programmierung bietet.

Das Beispiel der Baumstruktur wird zudem herangezogen, um das Konzept des Polymorphismus zu erl├Ąutern. Damit ist gemeint, dass eine Methode in den Unterklassen anders implementiert sein kann als in der Oberklasse und je nachdem welches Objekt gerade vorliegt, wird beim Aufruf der Methode die entsprechende Implementierung verwendet. Das hei├čt der Programmierer muss beim Erstellen des Quelltextes noch nicht wissen, mit welchem Objekt der Methodenaufruf stattfinden wird, aber er kann durch den Einsatz des Polymorphismus daf├╝r sorgen, dass f├╝r jedes Objekt die richtige Methode aufgerufen wird.