IT-Academy Logo
Sign Up Login Help
Home - Programmieren - C++ - C++ Grundlagen



C++ Grundlagen

Die Grundlagen von C++, vom Hallo Welt Programm bis zu einfachen Klassen. Status: zu 30% fertig.


Autor: Patrick Bucher (paedubucher)
Datum: 25-06-2004, 19:39:59
Referenzen: paedubucher@bluewin.ch
Schwierigkeit: Anfänger
Ansichten: 23524x
Rating: 7.4 (5x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Grundlagen

Allgemeine Informationen

Sämtliche Programme in dieser Dokumentation wurden mit "Microsoft Visual C++" getestet. Da es jedoch eine "ANSI-Norm" für C++ gibt, kann man die Programme auch mit anderen Compilern und derselben Schreibweise zum Laufen bringen.

Ein Projekt erstellen

Um ein C++ Projekt in Microsoft Visual C++ zu erstellen, muss man folgende Schritte ausführen:

Das Programm starten

Datei < Neu

Win32 Konsolenanwendung auswählen

Einen Namen für das Projekt wählen (Testprogramm...) < auf OK klicken

Die Option "Ein leeres Projekt" aktivieren < Fertigstellen

Datei < Neu

C++ Quellcodedatei auswählen und zum vorher erstellten Projekt hinzufügen.

Den Programmcode eingeben

Um das Programm zu starten, kann man "Strg-F5" drücken.

Ein "Hallo-Welt" Programm

Um die Syntax von C++ etwas zu veranschaulichen, habe ich hier ein typisches "Hallo Welt" Programm aufgeführt:

#include <iostream.h>

int main()

{

cout << "Hallo Welt!";

return 0;

}

Dieses Programm gibt die Textzeile "Hallo Welt" auf den Bildschirm aus. Die genauen Schritte werden später noch genauer erläutert, aber eine kurze Erklärung gebe ich trotzdem noch ab:

Die "Headerdatei" iostream.h wird ins Programm miteinbezogen. Durch diese werden einfache Ein- und Ausgaben auf den Bildschirm und andere Grundfunktionen ermöglicht. Falls man keine Headerdateien miteinbezieht, kann man keine Befehle angeben. Wenn nun der Befehl "cout" im Programm auftaucht, wird auf "iostream.h" verwiesen. "iostream.h" ist eine "Bibliothek" worin steht, wie ein Befehl ausgeführt werden soll.

"int main()" ist die "Hauptfunktion", welche beim Programmstart aufgerufen wird. Das "int" steht für den "Datentyp" der Funktion, d.h. der Rückgabewert der Funktion "main" muss vom Typ "int" (integer = Ganzzahl) sein, doch dazu später.

Die Funktion beginnt mit der geschweiften Klammer.

"cout" gibt einen Text auf den Bildschirm aus. << steht für "Ausgeben". Das Semikolon muss am Ende jedes Befehls stehen.

Die Funktion "int main" hat keinen Rückgabewert.

Die Funktion wird mit der geschweiften Klammer beendet.

Syntax Grundlagen
  1. Jede geöffnete Klammer oder Anführungszeichen muss wieder geschlossen werden.
  2. Jeder Befehl wird durch ; beendet, außer, wenn es Präprozessor-Anweisungen sind.
Die Funktion "cout"

Mithilfe der Funktion "cout" kann man Texte oder Zahlen auf dem Bildschirm ausgeben. Das wird mit folgender Syntax gemacht:

cout << "Auszugebender Text";

Man kann auch mehrere Texte/Zahlen auf dem Bildschirm ausgeben, dazu muss man jedoch "<<" mehrmals aufführen:

cout << "Die Zahl lautet:\t" << 5 << "\n";

Auf diese Weise kann man Strings verketten. Man kann natürlich auch Variablennamen einsetzen, dies tut man auf dieselbe Weise wie man Zahlen ausgibt. "\t" und "\n" sind sogenannte "Escape-Befehle". "\t" macht z.B. einen Tab, während "\n" einen Zeilenumbruch macht.

Einen Zeilenumbruch kann man auch mit dem "Manipulator" "endl" machen.

cout << "Die Zahl lautet:\t" << 5 endl;

Um Zahlen in einem bestimmten Format auszugeben, kann man den Datentyp in Klammern voranstellen.

cout << "Wissenschaftlich:\t" << (double) 5.2382;

cout << "Ganzzahl" << (int) 5;

Kommentare

Wie in (fast) jeder Programmiersprache, kann man auch in C++ Kommentare in den Programmcode einfügen. Kommentare haben 2 Aufgagen:

Beschreiben, was ein bestimmter Programmteil oder Befehl macht.

Programmbefehle in Kommentare ändern.

Der Sinn von Punkt 1 dürfte klar sein. Wozu aber Punkt 2? Wenn man einen Programmteil zu einem Kommentar umändert, wird dieser zwar nicht kompiliert, er bleibt aber im Programmcode. Dazu kann man auch die bedingte Kompilierung einsetzen (dazu später).

Kommentare einsetzen

Kommentare kann man in C++ auf zwei Arten einfügen:

Man schreibt zwei Schrägstriche // in eine Zeile. Alles was // folgt, wird vom Compiler ignoriert. Auf diese Weise kann man einzeilige Kommentare machen.

Wenn der Kommentar über mehrere Zeilen gehen soll, beginnt der Kommentar mit /* und endet mit */

Wie und wo man Kommentare einsetzt, bleibt dem Programmierer überlassen. Es ist jedoch zu empfehlen, so zu programmieren, dass man keine Kommentare benötigt, um den Programmcode zu verstehen. Kommentare verlangsamen das Programm aber nicht, da sie nicht kompiliert werden.

Beispiel am Hallo Welt Programm:

#include <iostream.h> // Headerdatei "iostream.h" includen

int main() // Hauptfunktion

{

cout << "Hallo Welt!"; // Ausgabe von "Hallo Welt"

Return 0; // Rückgabewert = 0

}

Es ist auch wichtig, Kommentare bei Änderungen am Programmcode mit abzuändern!

Variabeln Allgemein

Wenn man in einem Programm Werte speichern will, muss man Variabeln verwenden. Dazu muss man sich den Arbeitsspeicher eines PC's wie ein Regal vorstellen. Dieses Regal hat mehrere Fächer und in jedem Fach können Werte als Variabeln abgespeichert werden.

Variabeln deklarieren


Bei einer Variablendeklaration muss man den Namen und den Datentyp einer Variablen bekannt geben. Der Variablenname ist der eindeutige Schlüssel zur Adresse im Speicher. Diese braucht man aber glücklicherweise nicht mehr zu kennen, das übernimmt das Betriebssystem.

Links eine Übersicht über die Datentypen:

Heute ist es nicht mehr so wichtig, Platz im RAM zu sparen, wie früher. Früher hatte man vielleicht 256 kByte zur Verfügung, heute hat man normalerweise 256MB bis 1024MB.

Die Größe, die ein Datentyp im Speicher reserviert, kann mit der Funktion "sizeof" herausgelesen werden.

Cout << "Größe einer [Datentyp]-Variable:\t" << sizeof([Datentyp]);

Eine Variable wird im folgenden Syntax deklariert:

[Datentyp] [Variablenname];

Ein Variablenname darf dabei keine Leerzeichen oder "reservierte Wörter" haben. (Reservierte Wörter sind z.B. C++ Befehle.) Die Groß-/Kleinschreibung muss auch beachtet werden!

Ein Variablenname sollte zudem etwas über den Zweck der Variable aussagen.

Um mehrere Variablen mit einem Befehl zu deklarieren, muss man die einzelnen Variablen nur mit einem Komma voneinander trennen.

int x, y, z;

Vorzeichen

Wichtig ist es zu wissen, dass Variablen auch Vorzeichen, +/-, haben können. Eine "unsigned" (=ohne Vorzeichen) Variable vom Datentyp "short" hat einen Wertebereich von 0 – 65535. Wenn man aus "unsigned short" aber "signed short" macht, hat die Variable einen Wertebereich von -32768 bis 32767.

Um dem Compiler mitzuteilen, ob eine Variable mit oder ohne Vorzeichen deklariert werden soll, muss man nur das Schlüsselwort "signed" bzw. "unsigned" vorausstellen.

[signed/unsigned] [Datentyp] [Variablenname];

Die Zuweisung von Vorzeichen kann auch weggelassen werden, aber mit genauer Deklaration ist es "sauberer".

Werte zuweisen

Um einer Variablen einen Wert zuzuweisen, verwendet man den Zuweisungsoperator "=" . Die Variable, die den Wert erhält, muss unbedingt links stehen. Werte können schon bei der Deklaration zugewiesen werden oder zu jedem späteren Zeitpunkt.

Int integerVariable = 15, andereVariable = 55;

In C++ (wie auch in C) gibt es eine In- oder Dekrementsfunktion. Mit dieser Funktion kann man den Wert einer Variablen um 1 erhöhen oder verringern.

Int C;

C = 15;

C++;

cout << c;

Hier wird der Wert 16 ausgegeben. Das gleiche funktioniert auch mit "--". (Jetzt ist auch klar, warum C++ den Namen C++ hat, es soll die nächste Stufe von C darstellen.)

Typedef

Wenn man in einem Programm einen Datentyp verwendet, der sehr oft auftritt, kann man die Funktion "typedef" verwenden. Die Funktion "typedef" kann z.B. so aussehen:

typedef signed int TYP1;

Eine Variable kann nun bequem mit "TYP1" deklariert werden. Jetzt kann man einfach den oben zugewiesenen Datentypnamen und den Variablennamen aufführen.

TYP1 Ganzzahlvariable = 666;

Wichtig: "typedef" ist eine Präprozessor-Anweisung und darf so nicht in einer Funktion einprogrammiert werden, sondern muss im Präprozessor stehen!

Zeichen

Wenn man in einer Variabeln vom Typ "char" den Wert "a" ablegt, so hat diese einen Wert von 0 bis 255 (ASCII Code).

Globale Variablen

Sämtliche Variablen, die in einer Funktion deklariert werden, können nur von dieser einen Funktion angesprochen werden. Wenn man aber eine Variable will, die von allen Funktionen aus aufrufbar ist, benötigt man eine sogenannte "globale Variable". Die Deklaration einer globalen Variabel gestaltet sich genau so wie die Deklaration jeder lokalen Variable. Wichtig ist es nur, dass man die Deklaration in keine Funktion schreibt, sondern zwischen zwei Funktionen oder vor/nach der ersten/letzten Funktion. Wenn man eine globale Variable deklariert hat, kann man den gleichen Namen in einer Funktion für eine Variabeldeklarierung benutzen. Es wird dann die lokale Variable angesprochen. Man sollte jedoch keine doppelten Namen verwenden, das Programm wird zu unübersichtlich.

Globale Variabeln sollte man grundsätzlich meiden, wenn es möglich ist, die Variable als Parameter an eine Funktion zu übergeben.

Konstanten Der Sinn von Konstanten

Einer Variable soll man während der Laufzeit des Programms einen Wert zuweisen können. Wenn man aber Werte hat, die im Programm immer wieder auftreten, ist es mühsam jedes Mal die ganze Zahl hinzuschreiben (Beispiel: PI, Mehrwertsteuer...). Konstanten werden für Werte eingesetzt, die sich während der Programmlaufzeit nicht ändern.

Literale Konstanten

Eine literale Konstante ist ein Wert, den man direkt an eine Variable zuweist. Dieser kann z.B. 39 sein. Wenn man nun PI als literale Konstante haben will, müsste man den Kreisumfang möglicherweise so ausrechnen:

Kreisfläche = 3.14... * Radius;

So programmiert niemand (oder ein Anfänger).

Symbolische Konstanten

Eine Symbolische Konstante ist eine Variable, die man einsetzt, um z.B. zu rechnen. Die obige Rechnung würde mit einer symbolischen Konstanten "PI" etwa so aussehen.

float PI = 3.14...;

Kreisfläche = PI * Radius;

Wenn man nun PI an mehreren Stellen einsetzen muss, sieht man den Sinn von Konstanten schnell ein.

"Richtige" Konstanten

Für PI wäre es sinnvoll, wenn man aus ihr eine "echte" Konstante machen würde. Der Wert von PI könnte sich dann in der Laufzeit des Programms nicht mehr ändern. Konstanten werden im Präprozessor definiert. Dazu gibt es zwei Möglichkeiten:

Die Anweisung "#define"

Die Anweisung "const"

Um eine Konstante mit "#define" zu definieren, geht man wie folgt vor:

#define PI 3.14...

Es ist wichtig zu wissen, dass PI gar keinen Datentyp hat! Jedes mal wenn im Programmcode nun PI auftritt, wird vom Compiler 3.14... eingesetzt.

Um eine Konstante mit "#const" zu definieren, geht man so vor:

const unsigned int NumberOfTheBeast = 666;

Der Vorteil an "#define" ist dieser: man muss sich keine Gedanken um den Datentyp machen! Der größte Unterschied: "#define" ist eine Präprozessoranweisung, "const" ist ein normaler prozeduraler Befehl.

Aufzählungstypen

Mit der Funktion "enum" kann man neue Datentypen definieren. Syntax:

enum NAMEN { Hans, Sepp, Fritz, ...}

"NAMEN" ist der Name der Aufzählung. Hans ist das Element Nr. 0, Sepp ist das Element 1 usw. Den Index kann man auch manuell vergeben:

enum NAMEN { Hans=1000, Sepp=2000, Fritz=3000, ...}

Die Werte können nun bequem über den Index abgerufen werden.

Zur Erläuterung ein kleines Beispielprogramm, bei dem man den Wochentag auswählen kann:

#include <iostream.h>

int main()

{

enum Tage {Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag};

int Auswahl;

cout << "Geben sie einen Wochentag ein (0-6):\t";

cin >> Auswahl;

switch (Auswahl)

{

case Montag:

cout << "\nEs ist Montag";

break;

case Dienstag:

cout << "\nEs ist Diestag";

break;

default:

cout << "Es ist irgendein Tag";

break;

}

return 0;

}

Der Benutzer gibt die Zahl des Wochentages ein, das Programm gibt nun den Wochentag in Worten aus. Der "switch-case" Befehl wird später noch erklärt.

Anweisungen

Zuweisungen

Das Zuweisen von Werten an Variablen ist nicht nur in C++ ein wichtiges Thema, sondern in allen Programmiersprachen. Eine Zuweisung kann folgendermaßen aussehen:

C = A + B;

Die Gleiche Zuweisung kann natürlich auch so formuliert werden:

C=A+B;

C = A + B ;

Merke: in C++ kann man so viele Leerzeichen machen wie man will, der Code sollte dadurch aber nicht unübersichtlich werden.

Wie ist diese Zuweisung zu interpretieren? Ganz einfach: alles was links vom = steht, bekommt den Wert vom rechts des Gleichheitszeichens. Zuerst werden A und B addiert und anschließend wird der Wert in C gespeichert. Mathematisch wäre diese Zuweisung unmöglich:

C = C + 1;

Das würde ja bedeuten, C sei gleich gross wie C+1. Das wäre natürlich absoluter Schwachsinn. Das Gleichheitszeichen bedeutet jedoch nicht "gleichgroß", sondern "weise den Wert von rechts der Variablen links zu". Auch folgende Anweisung funktioniert perfekt:

A = B = 5 + 8;

• Zuerst bekommt B den Wert 5 + 8, also 13.

• Dann bekommt A den Wert von B, also 13.

Weitere zwei Zuweisungen. Welche funktioniert wohl?

X = 35;

35 = X;

Natürlich funktioniert nur die erste. X bekommt den Wert 35. In der Zweiten Anweisung bekäme die Zahl 35 den Wert X. Das ist aber unmöglich, da 35 halt mal 35 ist.

Mathematische Operatoren

C++ kennt folgende Grundlegende mathematischen Operatoren:

Addition: +

Subtraktion: -

Multiplikation: *

Division: /

Modulo Division: %

Zu den ersten 4 Operatoren bleibt nicht viel zu sagen. Etwas ist jedoch wichtig: wenn man mit "unsigned" Datentyp arbeitet, muss man aufpassen!

C = 50 – 60;

Sollte eigentlich den Wert -10 bekommen, das ist logisch. Da es sich aber um einen "unsigned" Datentyp handelt, gibt es keine negativen Werte. C würde nun einen Wert erhalten, der um 10 kleiner ist als der Integer-Maximalwert.

Die Modulo Divison dividiert zwei Zahlen und gibt den Rest zurück.

X = 22/7;

Y = 22%7;

Wenn X nun ein Integer ist, bekommt es den Wert 3. Y dann den Wert 1, denn 7 * 3 gibt 21, Rest 1.

Operatoren zusammensetzen

Wenn man eine Variable um 1 erhöhen will, verwendet man den Inkrementsoperator. Was tut man aber, wenn eine Variable z.B. um 10 erhöht/verringert werden soll? Man verwendet einen verknüpften Operator.

intX += 10;

intY -= 10;

Der erste Operator addiert/subtrahiert, das = weist dann den Wert erneut zu. Man kann auch die anderen Operatoren *, / und % dafür verwenden.

Weiteres zur In-/Dekrementierung

In- und dekrementieren kann man mit zwei Möglichkeiten. Entweder als Postfix oder als Präfix. Bei einem Postfix wird ++/-- nach dem Variablenname aufgeführt, beim Präfix vor dem Variablenname.

Postfix

X++;

X--;

Präfix

++X;

--X;

Wenn man nur die Variable um 1 erhöhen will, kommt es nicht darauf an, welche Art man anwendet. Wichtig ist es aber, wenn man eine Variable in- oder dekrementieren und ihren Wert an eine andere Variable zuweisen will.

Beim Präfix wird zuerst X um 1 erhöht und dann an Y zugewiesen.

Y = ++X;

Beim Postfix bekommt Y zuerst den Wert von X und dann wird X um 1 erhöht.

Y = X++;

Auswertungsreihenfolge

Auch in C++ gilt, Punkt vor Strich. Wenn nun zwei * oder / einander folgen, wird von links nach rechts ausgewertet. Um die Rangfolge zu ändern kann man Klammern benutzen. Klammern werden immer von innen nach aussen ausgewertet < wie in der Mathematik. Einige Beispiele:

X = 5 + 3 * 6; //3 * 6 = 18. 5 + 18 = 23.

X = 5 + 3 * 6 * 2; //3 * 6 = 18. 18 * 2 = 36. 5 + 35 = 41.

X = (5 + 3) * 2 //5 + 3 = 8. 8 * 2 = 16

X = ((5 + 3) + 7) //5 + 3 = 8. 8 + 7 = 15.


Wenn man komplexere Gleichungen hat, sollte man alles mit einer Anweisung berechnen. Man braucht keine Zwischenresultate, welche unter Umständen die Genauigkeit verschlechtern können. Falls die Genauigkeit keine Rolle spielt (nur Addition und Subtraktion), sollte man Zwischenvariabeln verwenden, da der Code übersichtlicher bleibt.

Entscheidungen

Datentyp "bool"

Der Datentyp bool kennt nur zwei Zustände. "True" und "False", bzw. 1 und 0 usw. Mit dem bool Datentyp kann man Prüfungen auf Variabeln machen, ob Variable1 größer ist als Variable2 usw. Vergleiche werden immer als boolean gespeichert, also, ob die Bedingung zutrifft oder nicht.

Vergleichsoperatoren

Um zwei Variablen zu überprüfen, ob sie gleichgroß sind, verwendet man einen Vergleichsoperator wie z.B. ==. Es ist wichtig == zum Vergleich zu verwenden, mit = macht man eine Zuweisung! Eine Übersicht über alle Vergleichsoperatoren:

Was kann man aber mit Vergleichsoperatoren bewerkstelligen? Hier beginnt ein Punkt, ohne den wohl kein Programm mehr auskommen kann – Entscheidungen.

Wozu Entscheidungen?

Bei allen Beispielen bis jetzt ist das Programm vom ersten bis zum letzten Befehl durchgelaufen. Der Benutzer konnte höchstens eine Zahl eingeben, es wurden immer die gleichen und alle Befehle durchgeführt. Wenn man nun z.B. ein Programm hat, mit dem man addieren und dividieren kann, woher weiß man, was der Benutzer tun will? Mit Entscheidungen! Bei einer Entscheidung werden zuerst ein oder mehrere Zustände geprüft. Wenn diese Bedingungen zutreffen, wird die Bedingung als Wahr angesehen, ansonsten als False. Es gibt kein teilweise oder vielleicht!

Die If Anweisung

Wenn man einen bestimmten Programmblock nur dann ausführen will, wenn eine bestimmte Bedingung zutrifft, verwendet man die "If" Anweisung (=Falls). Syntax:

Anweisung;

If (Logischer Ausdruck)

{

Anweisungsblock

}

Wenn man mehrere Anweisungen von der If-Abfrage abhängig machen will, muss man diesen Block in {} setzen.

Die If Anweisung prüft, ob der in den Klammern stehender Ausdruck wahr oder falsch ist. Man darf kein ; hinter den Logischen Ausdruck setzen! Wenn er wahr ist, führt er den Anweisungsblock in den {} aus, ansonsten fährt das Programm nach } weiter. Ein praktisches Beispiel:

If (Zahl1 >= Zahl2)

{

Cout << "Zahl1 ist größer oder gleich Zahl2";

}

Wenn Zahl1 größer oder gleich Zahl2 ist, wird die Meldung ausgegeben, ansonsten passiert nichts.

Was macht man aber, wenn man auch eine Meldung ausgeben will, wenn Zahl1 < Zahl2 ist? Man könnte zwei Bedingungen hintereinander aufführen!

If (Zahl1 >= Zahl2)
{

Cout << "Zahl1 ist grösser oder gleich Zahl2";

}

If (Zahl1 < Zahl2)

{

Cout << "Zahl1 ist kleiner als Zahl2";

}

Diese Variante ist nicht sehr unübersichtlich und wird in der Praxis nie verwendet. Um einen Befehlsblock festzulegen, was passieren soll, wenn die Bedingung nicht zutrifft, verwendet man die "Else" (=Sonst) Klausel. Ein Beispiel:

If (Zahl1 > Zahl2)

{

Cout << "Zahl1 ist grösser als Zahl2";

}

Else

{

Cout << "Zahl1 ist NICHT grösser als Zahl2";

}

Wenn die erste Bedingung nicht zutrifft, verweist das Programm in den Else-Anweisungsblock.

Verschachtelte If-Anweisungen

If-Anweisungen können auch verschachtelt werden. Beispiel:

If (Zahl1 >= Zahl2)

{

If (Zahl1 == Zahl2)

{

Cout << "Zahl1 ist gleich Zahl2";

}

Else

{

Cout << "Zahl1 ist ungleich Zahl2";

}

}

Else

{

Cout << "Zahl1 ist NICHT größer als Zahl2";

}

Zuerst wird geprüft, ob Zahl1 >= Zahl2 ist. Wenn das nicht zutrifft, wird ausgegeben, dass Zahl1 nicht größer als Zahl2 ist. Wenn ja, dann wird noch geprüft, ob die beiden Zahlen gleichgroß sind. Wenn sie gleichgroß sind, wird eine Meldung ausgegeben, dass sie gleichgroß sind. Ansonsten wird die Meldung ausgegeben, dass sie ungleich sind.

Mehrere Bedingungen prüfen

Wenn die If Bedingung nicht zutrifft, wird immer in else verzweigt. Was tut man aber, wenn man je nach Eingabe des Benutzers eine bestimme Meldung ausgeben will? Dafür gibt es den ElseIf Befehl.

Falls die If Prüfung nicht wahr ist, wird nun nicht mehr in den else Block verzweigt, sondern zuerst in die Elseif Blöcke. ElseIf prüft wie if auch eine Bedingung. Der allgemeine Syntax:

If (Ausdruck)

{

Anweisungen

}

Elseif (Ausdruck)

{

Anweisungen

}

Else

{

Anweisungen

}

Der Ausdruck zur Prüfung wird bei ElseIf genau so geschrieben, wie in If. Man kann theoretisch unbegrenzt viele ElseIf Einfügen, zu diesem Zweck eignet sich jedoch besser die switch-case Prüfung.

Logische Verknüpfungen

Damit man bei komplexeren Eingabeprüfungen keine If-Entscheidungen verschachteln muss, kann man logische Ausdrücke miteinander verknüpfen. Angenommen, es soll nur eine Ausgabe auf den Bildschirm erfolgen, wenn X und Y größer als 0 sind, wird die AND Verknüpfung genommen (&&).

If (X > 0 && Y > 0)

{

Cout << "X und Y sind größer als 0";

}

Statt AND einzutippen, muss man das entsprechende Symbol verwenden. Hier eine Übersicht über alle möglichen Verknüpfungssymbole in C++.


Bei der AND Verknüpfung müssen alle Bedingungen zutreffen, d.h. wahr sein. Um die Ausführgeschwindigkeit zu erhöhen, wird der zweite Teil gar nicht mehr geprüft, wenn der erste falsch ist. Der Geschwindigkeitsvorteil ist aber für heutige Prozessoren bei noch so komplexen Bedingungen für den Benutzer nicht sichtbar.

Die OR Verknüpfung benötigt nur gerade eine wahre Bedingung. Wenn hier der erste Ausdruck stimmt, wird der zweite Ausdruck nicht mehr überprüft.

NOT dient lediglich dazu, den Wahrheitswert umzukehren. Statt dem NOT Operator kann man auch einfach die Bedingung umformulieren. Trotzdem ein kurzes Beispiel:

If (!(x == 5)

{

Cout << "X ist nicht gleich 5";

}

Vorherige Bedingung würde man am besten so formulieren:

If (x != 5) // Ungleichheitsoperator

{

Cout << "X ist nicht gleich 5";

}

Auswertungsreihenfolge

Hier gilt, && bindet stärker als ||.

Mathematik: Punkt vor Strich

C++: UND vor ODER

If (x > 0 && y > 0 || x < 0 && y < 0)

Man muss den Sachverhalt nicht einmal wissen, da man auch Klammern benutzen kann. Ein Programmierer der Klammern benutzt, wird die Regel warscheinlich kennen, er wird aber Klammern zur Veranschaulichung benutzen.

Schreibweisen für Bedingungen

Wenn man prüfen will, ob ein Ausdruck 0 oder ungleich 0 ist, kann man eine Kurzschreibweise benutzen.

If (x)

Obige Schreibweise bedeutet: Wenn x zutrifft, also true, so ist die Bedingung erfüllt. Es wird also geprüft, ob x ungleich false (also 0) ist. Eine übersichtlichere und bessere Schreibweise wäre:

If (x != 0)

Der Bedingungsoperator

Mit dem Bedingungsoperator "?" können Bedingungen ohne if geprüft werden. Man sollte nicht mit diesem Operator programmieren, da diese Schreibweise sehr unübersichtlich ist – man muss solchen Programmcode jedoch lesen können.

Die Syntax des Bedingungsoperators:

(Bedingung) ? (Befehl wenn true) : (Befehl wenn false)

Ein Beispiel um zu testen, ob X grösser als Y ist. Wenn X grösser ist, wird der Wert an Z übergeben, sonst wird der Wert von Y übergeben.

z = (x > y) ? x : y;

Programmierschleifen Alt und verpönt – der goto-Befehl

Die ersten Schleifenkonstruktionen haben auf dem goto Befehl basiert. Man definiert eine Sprungmarke in einem Programm und kann beliebig oft und aus einem beliebigen Teil der Prozedur dort hin springen. Ein einfaches Beispiel:

Int main()

{

int n;

Sprungmarke:

n++;

If (n <= 10)

{

goto Sprungmakre;

}

[Befehlsblock]

}

Diese Schleife wird solange durchlaufen, bis n = 10 ist. Danach wird der Befehlsblock abgearbeitet. Der goto Befehl wurde früher sehr oft verwendet, was zu sehr unübersichtlichem und schlecht dokumentierbarem Programmcode führte.

Wenn man den goto Befehl behutsam einsetzt, kann er ganz praktisch sein. Man sollte die Verwendung von goto aber auf ein Minimun reduzieren.

Kopf- oder fußgesteuert?

Es gibt drei Arten von Programmierschleifen.

Als erstes die kopfgesteuerte Schleife. Diese Schleife prüft einen Umstand am Anfang und wird, falls die Bedingung nicht zutrifft, niemals durchlaufen.

Die fußgesteuerte Schleife wird mindestens einmal durchlaufen, da sie eine Abbruchbedingung am Schluss hat.

Die dritte Art sind Schleifen, die an sich keine Bedingung haben. Die Abbruchbedingung steht mitten in der Schleife, meistens mit einer if Abfrage und einer break Anweisung verknüpft.

Die while Schleife

Eine while Schleife wird solange durchlaufen, wie die Bedingung true ist. Es handelt sich hierbei um eine kopfgesteuerte Schleife. Der Syntax sieht so aus:

while (Bedingung)

{

Programmblock

}

Zur Veranschaulichung werden Zahlen von 1 bis 10 ausgegeben:

n = 1;

while (n<=10)

{

cout << n;

n++

}

Die Schleife wird solange durchlaufen, wie n kleiner gleich zehn ist. Es wird jedes Mal n ausgegeben und n wird danach jeweils um 1 vergrößert. Danach geht es wieder nach oben und die Bedingung wird erneut geprüft. Wenn 10 ausgegeben wurde, ist die Bedingung beim nächsten Test false, die Schleife wird verlassen und der erste Befehl nach der Schleife wird ausgeführt.

Endlosschleifen

Man kann mit der while Schleife auch Endlosschleifen produzieren. Dies wäre z.B. beim obigen Programmcode der Fall, wenn man n++ weglassen würde. Man könnte auch das Schlüsselwort true als Bedingung eingeben. Die Bedingung wäre immer wahr, da n immer = 1 bleibt.

n = 1;

while (n<=10)

{

cout << n;

}

Bei einer Endlosschleife gilt: sie bringt das Programm zum Einfrieren, da es unendlich oft durchlaufen wird. Eine Endlosschleife macht also keinen Sinn.

Endlosschleifen verlassen

Die Bedingung einer Schleife kann auch innerhalb von ihr stehen.

n = 1;

while()

{

cout << n;

n++

}

Diese Schleife wird unendlich oft durchlaufen, da keine Bedingung angegeben wurde. Mit dem Schlüsselwort break kann man die Schleife jedoch jederzeit verlassen:

n = 1;

while()

{

cout << n;

n++

if (n>10)

{

break;

}

}

Sobald n grösser als 10 ist, wird die Schleife mit dem break Befehl verlassen. Wenn man eine Schleife nicht ganz verlassen will, sondern nur unter einer bestimmten Bedingung die Schleife von oben her neu starten will, ohne dass spätere Befehle innerhalb der Schleife ausgeführt werden, kann man das Schlüsselwort continue verwenden.

int n = 1;

while(n<=10)

{

cout << n;

n++;

if (n>=5)

continue;

cout << n-1 << " ist kleiner als 5!";

}

Sobald n >= 5 ist, wird der Text nicht mehr ausgegeben.

Die do-while Schleife

Als fußgesteuerte Schleife wird in C++ die do-while Schleife eingesetzt. Diese wird immer einmal durchlaufen. Ihre Syntax sieht so aus:

do

{

Befehlsblock;

} while (Bedingung);

Als Beispiel eine kleine Eingabeprüfung, welche den Benutzer zwingt einen Wert zwischen 1 und 100 einzugeben.

do

{

cout << "\nBitte eine Zahl zwischen 1 und 100 eingeben\n";

cin >> Zahl;

} while (Zahl < 1 || Zahl > 100);

Hier würde eine while Schleife nichts bewirken, da sie unter Umständen kein einziges mal durchlaufen wird.

Die for-Schleife

Eine for-Schleife fasst Initialisierung, Bedingung und Veränderung der Durchlaufsvariablen in einem Klammerpaar zusammen. Sie ist kopfgesteuert. So sieht die Syntax dazu aus:

for (Initialisierung;Bedingung;Reinitialisierung)

{

Programmblock

}

Zwischen den einzelnen Teilen wird immer ein Semikolon eingefügt.

Das Beispiel einer while Schleife, welche die Zahlen von 1 bis 10 ausgibt, wäre mit einer for-Schleife deutlich einfacher zu lösen:

for(n=1;n<=10;n++)

{

cout << n;

}

Man kann auch beliebige Teile des Klammerinhaltes weglassen, das Semikolon müsste aber dennoch aufgeführt werden. So sähe eine Endlosschleife aus:

for(;;)

{

Programmblock

}

In einer for Schleife können auch mehr als eine Variable erhöht und geprüft werden. In diesem Fall muss man einfach die Teilausdrücke mit einem Komma trennen.

for(n=43,m=27;n<=66;n++,m+=15)

{

[Programmblock]

}

Die for-Schleife akzeptiert nicht nur die Vergrößerungen und Verkleinerungen von Zählvariablen, man kann auch Text auf den Bildschirm ausgeben, alle C++ Anweisungen sind gültig. Der Programmcode wird jedoch sehr unübersichtlich.

Eine Zählervariable kann auch innerhalb einer for-Schleife deklariert werden.

for(int i = 0;i<=10;i++)

{

}

Wichtig ist es zu wissen, dass Variablen, welche im for-Schleifenkopf deklariert wurden nach dem neuen ANSI Standard nur innerhalb dieser Schleife gültig sind.

Man muss selber herausfinden, wie der verwendete Compiler mit solchen Deklarationen umgeht.

Schleifen können auch beliebig verschachtelt werden. Viele Programmierprobleme sind nur durch eine solche Verschachtelung zu lösen!

Die Switch-Case Anweisung

Wenn man je nach Wert einer Variable bestimmte Aktionen ausführen will, kann man dies mit mehreren If und Else If Entscheidungen machen. Der Code wird auf diese Weise jedoch sehr unübersichtlich. Besser ist es, eine Swicht-Case Anweisung zu benutzen.

Der Syntax sieht so aus:

switch (Ausdruck)

{

case Wert1:

{

[Programmblock]

break;

}

case Wert2:

{

[Programmblock]

break;

}

default:

{

[Programmblock]

break;

}

}

Für Ausdruck kann man jeden beliebigen C++ Ausdruck auf seinen Wert prüfen. Das Schlüsselwort case wird vor den möglichen Wert des Ausdrucks gestellt. Danach folgt ein Doppelpunkt um den Anweisungsblock einzuleiten. Dieser sollte in geschweiften Klammern stehen. Der break Befehl teilt dem Compiler mit, dass hier mit der Abarbeitung der Anweisungen aufgehört werden soll, ansonsten werden alle Programmblöcke ausgeführt!

Das Schlüsselwort default teilt dem Compiler den Programmblock mit, welcher ausgeführt werden soll, wenn keiner der aufgeführten Werte zutrifft. Es können beliebig viele Werte aufgeführt werden.

Oft prüft man keine C++ Ausdrücke sondern lediglich Variablen.

Funktionen

Was ist eine Funktion?

Bisher wurde nur die Funktion "main" verwendet. "main" wird beim Programmstart automatisch gestartet. Funktionen dienen dazu, ein Programm in bestimmte "Unterprogramme" zu teilen. Statt Funktionen zu verwenden, kann man natürlich auch den gesamten Programmcode in "main" schreiben. Warum verwendet man also Funktionen?

Wenn ein Teil des Programms mehrmals ausgeführt werden soll, kann einfach und bequem die Funktion aufgerufen werden.

Wenn man ein Programmteil mehrmals aufgeführt hat, muss man jeden Teil einzeln abändern. Wenn man Funktionen benutzt, muss man nur einen Teil verändern.

Funktionen machen den Programmcode übersichtlicher, Wartungen sind einfacher und schneller.

Angenommen, man hat ein Programm, das in bestimmten Fällen eine Fehlermeldung ausgeben soll. Entweder, man fügt die Fehlermeldung jedes Mal ein, oder man verwendet eine Funktion.

#include <iostream.h>

void Fehlermeldung()

{

cout << "Es ist ein Fehler aufgetreten";

}

int main()

{

[Irgendwelche Befehle]

Fehlermeldung

[Irgendwelche Befehle]

Fehlermeldung

return 0;

}

Jedes mal, wenn der Compiler auf "Fehlermeldung" stösst, verzweigt er nun auf diese Fehlermeldung. Diese Funktion hat den Datentyp "void", d.h. sie gibt nichts zurück. Wenn man nun eine Funktion zur Addition von Ganzzahlen programmiert, muss der Datentyp "int" sein.

Aufbau einer Funktion

Eine Funktion besteht jeweils aus einem "Kopf" und einem "Rumpf". Der Funktionskopf für eine einfache Additionsfunktion könnte so aussehen.

int Summe(int a, int b)

Diese Funktion ist vom Datentyp "int", d.h. sie gibt einen Ganzzahlwert zurück. Außerdem erwartet die Funktion zwei "Argumente", a und b. Beide Argumente haben den Datentyp "int". Ein Argument wird innerhalb einer Funktion als lokale Variable behandelt.

Im Rumpf der Funktion können null bis x Befehle stehen. Die Funktion kann natürlich auch zu einer weiteren verzweigt werden. Jede Funktion wird von { } umschlossen. Um ein Ergebnis wiederzugeben, wird der Befehl "return" benutzt (= Rückgabe). Nach "return" geschieht in einer Funktion nichts mehr.

Funktionen anwenden

Zur Erläuterung ein kleines Beispiel für ein Programm, das Ganzzahlen entgegennimmt und in einer Funktion addiert.

#include <iostream.h>

int Add(int x,int y)

{

return(x+y);

}

int main()

{

int a,b,c;

cin >> a;

cin >> b;

c = Add(a,b);

cout << c;

return 0;

}

Interessant ist an diesem Beispiel vor allem der Funktionsaufruf. Der Befehl cin >> dient dazu, eine zahl von der Tastatur entgegenzunehmen. (Hier muss man >> statt << verwenden!).

Das Programm liest zwei Variablen ein. Der Variable c wird dann der Wert Add(a,b) zugewiesen. Bei Add verzweigt das Programm zur Funktion "Add", die zwei Argumente erwartet. Diese werden beim Aufruf in der entsprechenden Reihenfolge aufgeführt. Die Funktion "Add" gibt nun die Summe von (x+y) zurück.

Funktionsprototyp

Funktionen können nur aufgerufen werden, wenn sie oberhalb der Funktion "main" einprogrammiert wurden. Dies schadet jedoch der Übersicht, da man main lange suchen muss. Statt main als letztes zu schreiben, deklariert man am Anfang des Programms, dass bestimmte Funktionen noch folgen werden. Diese Deklaration nennt man "Funktionsprototyp".

Wenn nun z.B. eine Funktion "add" unter main folgen soll, muss der Prototyp so aussehen.

Int add(int a, int b);

Sie enthält den Funktionskopf, der Funktionsrumpf wird weggelassen. Man muss beachten, dass die Deklarierung eines Prototyps eine Anweisung ist, also muss ";" folgen. Sobald main mit { beendet ist, kann man die Funktion "add" programmieren, mit Funktionskopf und -rumpf.

Rückgabewerte

Ein Rückgabewert wird immer mit dem Schlüsselwort "return" zurückgegeben. Hier einigen Beispiele, wie man Werte zurückgeben kann:

Return(X); //Rückgabe einer Variablen X

Return(X > 5); //Liefert den Wert True oder False, wenn X >/< 5 ist

Return(sqrt(X)); //Gibt die Wurzel der Variable X zurück

Rückgabewerte können also auch Funktionen enthalten, falls diese Funktionen selber einen Rückgabewert haben. Letzteres kann man auch mit den Parametern machen.

Bei Return kehrt die Funktion wieder zu main zurück, und zwar einen Befehl nach dem Funktionsaufruf. Wenn in der Funktion noch Befehle nach return stehen, werden diese nicht beachtet.

Standardparameter

Wenn der Benutzer keine Werte für die Parameter eingibt, kann die Funktion nicht funktionieren. Deshalb benutzt man Standardparameter.

int meineFunktion(int x = 63, int y = 54)

Funktionen überladen

Angenommen, man hat 4 Funktionen, die eine Zahl verdoppeln sollen. Jede dieser Funktionen soll mit einem anderen Datentyp arbeiten. Man muss nun nicht 4 Funktionen mit verschiedenen Namen deklarieren, man kann auch 4-mal den gleichen Funktionsnamen angeben, nur dass diese Funktionen jeweils unterschiedliche Parametertypen haben. Hier ein Beispiel:

Int Verdoppeln(int zahl);

long Verdoppeln(long zahl);

float Verdoppeln(float zahl);

double Verdoppeln(double zahl);

Jetzt kommt es alleine darauf an, welchen Datentyp die übergebenen Parameter haben. Die entsprechende Funktion wird dann aufgerufen.

Man kann auch in der Anzahl der Parameter variieren!

Inline Funktionen

Das Herumspringen zwischen Funktionen kostet mehr Leistung, als das Abarbeiten von oben nach unten. Bei einer kleinen Funktion, die z.B. nur eine Zahl verdoppeln soll, sollte man nun nicht einen Sprung quer durch den Arbeitsspeicher machen. Schneller ginge es, wenn der Compiler die Funktion einfach umschreiben und an die Stelle des Funktionsaufrufes legen würde. So hat man trotzdem übersichtlichen Programmcode und auch optimale Geschwindigkeit. Um eine Inline Funktion definieren zu können, muss man nur das Schlüsselwort "inline" voranstellen.

inline int verdoppeln(int zahl);

Der Geschwindigkeitsgewinn auf heutigen Geräten, bleibt so gut wie unbemerkbar.

Rekursion

Funktionen können sich auch selber aufrufen. Wenn eine Funktion sich selber aufruft, dann nennt man das direkte Rekursion. Wenn Funktion1 nun Funktion2 aufruft und diese wiederum Funktion1 aufruft, ist die Rede von einer indirekten Rekursion.

Wenn eine Funktion sich selbst aufruft, wird eine Kopie dieser Funktion erstellt, die lokalen Variablen sind also andere als bei der Ursprungsfunktion!

Rekursive Funktionen benötigen eine Abbruchbedingung, sonst hängt sich das Programm auf. Eine Funktion beendet man bekanntlich mit einem return Befehl.

Klassen

Bisherige Klassen

Sämtliche Datentypen wie Integer, Long und Double sind Klassen. Jede Variable hat also gewisse Eigenschaften wie maximaler und minimaler Wert, Größe im Speicher oder Nachkommastellenanzahl.

Wozu Klassen definieren?

Alltägliche und natürliche Gegebenheiten kann man nicht immer mit Zahlen darstellen. Deshalb definiert man neue Typen. Mit eigenen Klassen kann man also sehr "natürlich" programmieren, was die Arbeit sehr erleichtern kann.

Eine Klasse könnte z.B. "Auto" heißen und alle Teile eines Autos zusammenfassen wie Anzahl Sitze, Anzahl Zylinder, Tankvolumen, PS usw. Eine Klasse könnte auch die Funktionen zusammenfassen, z.B. fahren, bremsen, parken usw. Diese Funktionen werden als Methoden bezeichnet.

Klassen definieren

Die Definition einer Klasse wird immer mit dem Schlüsselwort "class" vorgenommen. Danach folgt der Klassenname und in geschweiften Klammern die Methoden und Eigenschaften. Zur Veranschaulichung die Klasse Mensch:

Class Mensch

{

Double itsGewicht;

Double itsGrösse;

Double itsIQ;

Gehen();

Schlafen();

Denken();

};

Die ersten drei Zeilen innerhalb der geschweiften Klammern definieren Eigenschaften (wie ein Mensch ist), die nächsten drei Zeilen definieren Methoden (was ein Mensch tun kann). Bei Klassen verwendet man das Präfix "its" (=sein), um die Variabeln als Teil einer Klasse zu definieren.

Nicht zu vergessen, ist das Semikolon nach der abschließenden geschweiften Klammer! Eine Klasse ist keine Prozedur, sondern viel mehr eine Anweisung.

Was ist nun ein Objekt?

Mensch ist nur die Klasse (oder der Typ) eines Objekts. Objekte der Klasse "Mensch" sind nun einzelne Individuen. Die Variable intZahl ist auch nichts weiteres als ein Objekt der Klasse Integer.

Objekte deklarieren

Ein Objekt wird genau so, wie eine normale Variable deklariert. Wenn eine Deklaration einer Integer Variable so aussehen würde,

Int intMeineVariable;

so sähe die Deklaration des Objekts "Peter" der Klasse "Mensch" so aus:

Mensch Peter;

Man sollte sich auch Gedanken über Präfixe eigener Klassen machen, mnsPeter würde etwas mehr über das Objekt aussagen.

Auf Objekte zugreifen

Um auf Methoden und Eigenschaften eines Objekts zugreifen zu können muss man das Objekt mit einem Punkt von der Methode oder der Eigenschaft trennen.

Peter.itsGrösse = 177;

Peter.Gehen();

Gültigkeitsbereich

Die Variablen in einer Klasse werden, wenn man nichts vorausstellt, als Private deklariert. D.h. die Variablen können nur von Methoden der aktuellen Klasse angesprochen werden. Wer das nicht weiß, dem wird es nicht gelingen einer Eigenschaft eines Objekts einen Wert zuzuweisen! Damit Eigenschaften auch öffentlich angesprochen werden können, muss man das Schlüsselwort Public voranstellen.

Class Mensch

{

Public:

itsAlter;

itsGroesse;

};

Allgemein gilt, dass man Eigenschaften privat halten sollte und die Eigenschaften nicht direkt aus dem Programm heraus mit Werten belegt. Um diese Eigenschaften dennoch mit einem Wert zu initialisieren verwendet man "Zugriffsmethoden". Man definiert innerhalb der Klasse Funktionen, welche Argumente entgegennehmen und diese an Eigenschaften zuweisen. Auf diese Weise hat man ein besser wartbares Programm.

Klassenfunktionen definieren

Die oben angesprochenen Zugriffsmethoden kann man allerdings nicht in der Klasse definieren, man muss dies außerhalb tun. Damit man eine Funktion der entsprechenden Klasse definiert und nicht irgendeine Funktion, muss man so vorgehen:

Datentyp Klasse::Funktionsname(Parameterliste)

{

[Codeblock]

}

Jetzt werden innerhalb der Klasse nur noch die Funktionsprototypen aufgeführt. Wenn man die Funktionen innerhalb der Klasse aufführt, wird diese zugleich als inline Funktion definiert. Hier ein Beispiel zur Veranschaulichung:

#include <iostream.h>

class clsMensch

{

private:

unsigned int itsAlter;

public:

int getAlter();

void setAlter(unsigned int Alter);

};

void clsMensch::setAlter(unsigned int Alter)

{

itsAlter = Alter;

}

int clsMensch::getAlter()

{

return itsAlter;

}

int main()

{

clsMensch Hubertus;

Hubertus.setAlter(35);

cout << "Hubertus ist: " << Hubertus.getAlter() << " Jahre alt.";

return 0;

}

In diesem Programm ist fast alles aufgeführt, was oben angesprochen wurde.

Konstruktoren und Destruktoren

Wenn man eine Variable deklariert, kann man ihr auch zusätzlich einen Wert zuweisen.

int Zahl = 31;

Diesen Wert kann man später im Programm jederzeit wieder ändern, die Variable hat nun einfach einen "Standardwert" erhalten, falls der Benutzer keinen Wert für die Variable eingibt.

Wenn man bei einer Klasse z.B. will, dass bei einer Definition eines Menschen unbedingt dessen Alter bekannt gegeben werden muss, kann man auf Konstruktoren zurückgreifen. So kann man sich zum Beispiel einen weiteren Funktionsaufruf ersparen. Der Konstruktor hat jeweils denselben Namen wie die Klasse. Die Definition eines Konstruktoren, der das Alter eines Menschen aufnimmt, würde so aussehen:

class clsMensch

{

private:

unsigned int itsAlter;

public:

clsMensch(int Alter);

int getAlter();

};

Auf diese Weise spart man sich gegenüber der obigen Klasse die Funktion setAlter ein, man muss jedoch eine Funktion clsMensch::clsMensch definieren. Was soll das nun bringen? Angenommen, man definiert keinen Konstruktor, würde der Compiler dem Programm dennoch nachträglich (im Hintergrund) einen Konstruktor hinzufügen. Man macht dies nur, um Standardkonform zu bleiben.

Es verbirgt sich jedoch noch ein weiterer Vorteil hinter dem Ganzen. Ein Objekt, das mit dem Konstruktor initialisiert wurde, verbraucht Speicherplatz. Wenn dieses Objekt jedoch nicht mehr gebraucht wird, bleibt es weiter im Speicher. Wenn der Programmierer nun weiß, ab welchem Zeitpunkt ein Objekt nicht mehr verwendet wird, kann er das Objekt zerstören. Dies tut man mit dem Destruktor.

Die Definition des Prototypen eines Destruktors sieht gleich aus, wie beim Konstruktor, nur dass man eine Tilde (~) voranstellt. Die Definition der Funktion sieht dann so aus:

clsMensch::~clsMensch()

{

}

Ein Konstruktor oder Destruktor hat keinen Rückgabewert, nicht einmal den Rückgabewert void!

Das Objekt kann nun im Programm an beliebiger Stelle zerstört werden, indem man den Destruktor aufruft.

Hubertus.~clsMensch();

Ein Objekt braucht, bezogen auf die heutigen RAM's, so gut wie kein Speicher. Das Zerstören eines Objekts bringt also eigentlich nichts. Man wendet Konstruktoren und Destruktoren jedoch immer noch in der Praxis an, um einen sauberen Programmierstil beizubehalten. Bei größeren Applikationen ist es jedoch günstig, wenn von Anfang an Ressourcen von Geräten gespart wird.

Konstante Methoden

Es gibt Methoden, welche den Wert einer Eigenschaft verändern müssen und Methoden, welche nur einen Wert zurückgeben müssen. Um sicherzustellen, dass eine Methode keine Eigenschaft verändern kann, muss man der Methode das Schlüsselwort "const" nachstellen. Zur Veranschaulichung ein Prototyp:

void getAlter() const;

Wenn man nun aus Versehen mit der Methode getAlter den Wert einer Eigenschaft eines Objekts ändern will, wird der sich der Compiler sofort zu Wort melden. Das kann bei der Fehlersuche sehr nützlich sein, deshalb definiert man sämtliche Methoden, die keine Eigenschaften verändern sollen mit const!

Klassenimplementierungen platzieren

Bei obigen Beispielprojekten wurden alle Klassen- und Methodendefinitionen mit den übrigen Funktionen in eine Datei geschrieben. Bei kleinen Projekten mag das schön und gut sein, bei größeren Projekten leidet die Übersicht sehr stark darunter!

Deshalb speichert man Klassendefinitionen mitsamt deren Methoden in eine eigene Datei mit der Endung .hpp. Die Klasse kann nun bequem über einen #include Befehl eingelesen werden.

#include <mnsMensch.hpp>

Auf diese Weise kann man Klassen auch an andere Programmierer weitergeben, die dann damit arbeiten können. So kann man auch mit Funktionen vorgehen, indem man sie in eine eigene Datei mit der Endung .h speichert.

Klassen können Elemente von Klassen sein

Angenommen, man hat eine Klasse Mensch. Dieser Mensch hat zwei Arme. Was tut man, wenn man nun die Anzahl der Muskeln und Knochen beschreiben will? Man definiert neben der Klasse Mensch eine Klasse Arm mit den Eigenschaften itsKnochen, itsMuskeln usw. Je realitätsnäher man programmiert, desto besser ist das Programm!

Strukturen

Neben den Klassen gibt es in C++ auch "Strukturen". Der einzige Unterschied zur Klasse ist dabei, dass man Klassen mit dem Schlüsselwort "class" definiert, bei Strukturen ist es das Schlüsselwort "struct". Ein weiterer Unterschied ist, dass bei Strukturen die Eigenschaften und Methoden standardmäßig öffentlich sind, was bei einem guten und sauberen Programmierstil nichts ändert.

Referenzen: C++ in 21 Tagen, Markt und Technik Verlag, ISBN: 3827268893



[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06246
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1154
Comments: 0