C++: Fortgeschrittene Syntax

Inhaltsverzeichnis und Lernziele des Kapitels C++: Fortgeschrittene Syntax.

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:

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

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:

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:

Es ist daher unbedingt nötig, dass Sie einige Übungen absolvieren, bei denen Sie:

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:

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

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:

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.