Im letzten Artikel wurde der Heap in seiner allgemeinen Funktionsweise vorgestellt. Bevor wir uns allerdings weiter mit Pointern beschäftigen, wollen wir zuerst ein anderes Thema besprechen, und zwar dass der strukturierten Datentypen.
Die bisher bekannten Datentypen sind lediglich dazu geeignet, um einzelne Werte (etwa Zahlen oder einzelne Buchstaben) zu speichern. In Arrays können zwar mehrere Werte gespeichert werden, jedoch nur welche vom gleichen Datentyp. Oft ist es aber auch nötig, Werte unterschiedlicher Datentypen zusammen zu speichern, wenn etwa komplexere Sachverhalte ausgedrückt werden sollen.
Zwar könnte man zu diesem Zweck natürlich mehrere Variablen unterschiedlicher Datentypen anlegen und in diesen die zusammengehörenden Werte speichern. Das hat natürlich aber zum einen den Nachteil, dass eigentlich zusammengehörende Werte nicht gebündelt gespeichert werden, und zum anderen, dass beim Übergeben dieser Werte als Argumente bei Funktionsaufrufen immer mehrere Werte übergeben werden müssen. Nehmen wir zum Beispiel an, wir wollen eine rationale Zahl als Verhältnis zweier ganzer Zahlen darstellen. Momentan haben wir dafür nur die folgende Möglichkeit, nämlich über die Verwendung zweier Variablen für Zähler und Nenner (im Beispiel wird der Bruch 1/2 in den Variablen gespeichert):
int numerator; int denominator; numerator = 1; denominator = 2;
Ein zweiter Bruch parallel dazu lässt sich nur so darstellen:
int numerator1; int denominator1; int numerator2; int denominator2;
Wir sehen, dass wir für eigentlich 2 Daten (die 2 Brüche) bereits 4 Variablen benötigen; wollen wir nun etwa eine Funktion schreiben, welche 2 rationale Zahlen miteinander multipliziert, müssen wir ihr bereits 4 Variablen übergeben. Noch schlimmer aber: welchen Wert soll die Funktion zurückliefern? Schauen wir uns einmal die Implementierung der Funktion an, deuten die Stellen mit den Fragezeichen bereits an, wo es Probleme geben könnte (C++-Kenner werden wissen, dass man das Problem natürlich auch so lösen kann, aber dazu in einem späteren Artikel mehr):
??? fractionMultiplication( int numerator1, int denominator1, int numerator2, int denominator2 ) { int numerator = numerator1 * numerator 2; int denominator = denominator1 * denominator2; return ???; }
Was wir benötigen, ist eine Möglichkeit, um die rationale Zahl mit Zähler und Nenner in einer einzigen Variable zu speichern. Die bisher bekannten Datentypen erlauben aber nicht die Speicherung von derartig notierten rationalen Zahlen; zudem können wir uns beliebige Datenstrukturen ausdenken, die aus mehreren Werten bestehen. Was wir also eigentlich benötigen, ist eine Möglichkeit, eigene, komplexe Datentypen zu beschreiben. Eine Möglichkeit, um das in C++ zu tun, ist die Verwendung sogenannter strukturierter Datentypen oder structs
.
structs
werden in C++ deklariert, indem sie zuerst mit einem Namen versehen und anschließend die einzelnen Bestandteile der Struktur – ebenfalls benannt – aufgezählt werden. Eine Struktur für rationale Zahlen könnte also etwa so aussehen:
struct Fraction { int numerator; int denominator; };
Sie trägt den Namen Fraction
und verfügt über die beiden Bestandteile numerator
und denominator
. Prinzipiell kann die Struktur an (fast) beliebiger Stelle im Code deklariert werden, gilt dann aber auch nur in dem Bereich, in welchem sie deklariert wurde (also etwa innerhalb einer Funktion); idealerweise deklariert man die Struktur deshalb außerhalb von Funktionen. Außerdem müssen Strukturen vor ihrer ersten Verwendung im Code deklariert werden – das ist eine Eigenheit von C++, etwa gegenüber C# oder Java.
Hat man eine neue Struktur deklariert, kann sie wie ein normaler Datentyp zur Deklaration von Variablen benutzt werden, in unserem Fall also etwa so:
Fraction frac;
Unsere Funktion für das Multiplizieren zweier rationaler Zahlen lässt sich also schon einmal beträchtlich verbessern:
Fraction fractionMultiplication( Fraction frac1, Fraction frac2 ) { Fraction result; ??? return result; }
Bleibt nur noch die Frage, wie man denn das Ergebnis berechnet – und im Zusammenhang damit, wie man überhaupt Werte an eine Variable zuweist, die als ein strukturierter Datentyp deklariert ist. Die übliche Art der Zuweisung geschieht, indem den einzelnen Bestandteilen einer Struktur-Variablen explizit Werte zugewiesen werden; der Zugriff auf einen solchen Bestandteil erfolgt durch Verwendung des Punkt-Operators, gefolgt vom Namen des Bestandteils. Unsere Funktion lässt sich damit also so vollenden:
Kommentare (7)