vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 1



Erste Schritte

Willkommen zu C++ in 21 Tagen! Heute werden Sie die ersten Schritte machen, mit dem Ziel, ein erfolgreicher C++-Programmierer zu werden. Sie lernen,

Ein kurzer geschichtlicher Abriß der Programmiersprache C++

Programmiersprachen haben seit den ersten elektronischen Computern, die zur Berechnung der Flugbahnen von Kanonenkugeln im 2. Weltkrieg gebaut wurden, eine dramatische Wandlung erfahren. In der Gründerzeit arbeiteten die Programmierer mit den primitivsten Computer-Anweisungen: Maschinensprache. Diese Anweisungen stellte man durch lange Folgen von Einsen und Nullen dar. Mit Einführung der Assembler ließen sich die Maschinenanweisungen durch besser verständliche Mnemonics wie ADD und MOV abbilden.

Im Laufe der Zeit entstanden höhere Programmiersprachen wie BASIC und COBOL. Diese Sprachen erlauben die Arbeit in einer der natürlichen Sprachen (in der Regel Englisch) ähnlichen Sprache wie Let I = 100. Diese Anweisungen übersetzen Interpreter und Compiler in die Maschinensprache. Ein Interpreter liest den Quellcode eines Programms, übersetzt dabei die Anweisungen - oder den Code - und wandelt sie direkt in Aktionen um. Ein Compiler überführt den Code in eine Art Zwischenform - diesen Schritt nennt man Kompilieren - und erzeugt damit eine Objektdatei. Der Compiler ruft anschließend einen Linker auf, der die Objektdatei in ein ausführbares Programm umwandelt.

Da Interpreter den Code genauso lesen, wie er niedergeschrieben wurde, und den Code unmittelbar ausführen, stellen sie ein leicht anzuwendendes Arbeitsmittel für den Programmierer dar. Bei Compilern sind zusätzliche Schritte zum Kompilieren und Linken des Codes erforderlich, was etwas umständlicher ist. Andererseits produzieren Compiler ein Programm, das wesentlich schneller in der Ausführung ist, da die zeitraubende Aufgabe, den Quellcode in die Maschinensprache umzuwandeln, bereits erledigt wurde.

Ein weiterer Vorteil vieler kompilierter Sprachen wie C++ ist, daß das ausführbare Programm auch an Leute weitergegeben werden kann, die nicht über den Compiler verfügen. Bei einem Programm, das mit Interpreter-Sprache erstellt wurde, müssen Sie zur Ausführung des Programms auch den Interpreter haben.

Einige Sprachen, zum Beispiel Visual Basic, nennen den Interpreter die Laufzeit-Bibliothek. Bei Java heißt der Laufzeit-Interpreter Virtuelle Maschine (VM) und wird im übrigen von den Browsern (das heißt Internet Explorer oder Netscape) zur Verfügung gestellt.

Über viele Jahre hinweg bestand das hauptsächliche Ziel der Programmierer darin, kurze und schnelle Codestücke zu schreiben. Das Programm mußte klein sein, da Hauptspeicher teuer war, und es mußte schnell sein, da Rechenzeit ebenfalls einen nicht unerheblichen Kostenfaktor darstellte. Computer wurden kleiner, billiger und schneller, die Speicherpreise sind gefallen, und somit haben sich die Prioritäten geändert. Heutzutage überwiegen die Kosten für einen Programmierer bei weitem die Kosten der meisten geschäftlich genutzten Computer. Gut geschriebener und leicht zu wartender Code steht nun an erster Stelle. Leicht zu warten bedeutet dabei, daß sich das Programm bei sich ändernden Anforderungen ohne großen Kostenaufwand erweitern und verbessern läßt.

Programme

Das Wort Programm wird in zweierlei Hinsicht benutzt: zur Beschreibung einzelner Anweisungen (oder Quellcodezeilen) eines Programmierers oder zur Beschreibung einer kompletten, ausführbaren Software. Diese Unterscheidung kann einige Verwirrung hervorrufen. Deshalb werde ich hier in dem einen Fall von Quellcode und im anderen Fall von ausführbarem Programm sprechen.

Ein Programm kann entweder definiert werden als ein Satz geschriebener Anweisungen eines Programmierers oder als eine ausführbare Software-Datei.

Es gibt zwei Möglichkeiten, Quellcode in ein ausführbares Programm zu überführen: Interpreter übersetzen den Quellcode in Computerbefehle, und der Computer führt diese Befehle sofort aus. Alternativ kann der Quellcode von Compilern in ein Programm überführt werden, das zu einem späteren Zeitpunkt gestartet werden kann. Zwar sind Interpreter in der Anwendung einfacher, doch ernsthaft programmiert wird vornehmlich mit Compilern, da kompilierter Code wesentlich schneller ausgeführt werden kann. C++ ist so eine kompilierte Programmiersprache.

Probleme lösen

Die Probleme, mit denen Programmierer im Laufe der Jahre konfrontiert wurden, haben sich erheblich geändert. Vor zwanzig Jahren wurden Programme erzeugt, um große Mengen an Rohdaten zu verarbeiten. Die Erzeuger des Codes und die Nutzer des Programms waren ausnahmslos Computerexperten. Heutzutage werden Computer von wesentlich mehr Menschen genutzt, die zum größten Teil über nur begrenzte Computer- und Programmierkenntnisse verfügen. Computer sind lediglich Werkzeuge, die von Menschen genutzt werden, die eher daran interessiert sind, ihre Firmenprobleme zu lösen als sich mit dem Computer abzumühen.

Ironischerweise sind die Programme im gleichen Zuge komplexer geworden, wie es dem neuen Anwenderkreis einfacher gemacht wurde. Die Tage sind vorbei, als Benutzer kryptische Befehle hinter esoterischen Prompts eingaben, nur um einen Strom Rohdaten zu sehen. Heute verfügen Programme über anspruchsvolle, benutzerfreundliche Schnittstellen mit einer Unzahl von Fenstern, Menüs, Dialogfeldern und einer Myriade von Symbolen, mit denen wir alle inzwischen nur zu vertraut sind. Die Programme, die diesen neuen Ansatz unterstützen, sind wesentlich komplexer als jene, die vor zehn Jahren geschrieben wurden.

Mit der Entwicklung des Webs haben Computer einen neue Ära der Marktdurchdringung eingeläutet. Mehr Menschen als je zuvor benutzen Computer und ihre Erwartungen sind sehr hoch. In den wenigen Jahren seit der ersten Auflage dieses Buches sind die Programme umfangreicher und komplexer geworden, und der Bedarf an Techniken der objektorientierten Programmierung, um dieser Komplexität Herr zu werden, zeigt sich jetzt deutlich.

Im gleichen Maße wie sich die Anforderungen an die Programme geändert haben, haben sich auch die Programmiersprachen und die Techniken zum Schreiben von Programmen weiterentwickelt. Auch wenn der ganze Werdegang interessant ist, konzentriert sich dieses Buch auf den Übergang von der prozeduralen zur objektorientierten Programmierung.

Prozedurale, strukturierte und objektorientierte Programmierung

Bis vor kurzem stellte man sich Programme als eine Folge von Prozeduren vor, die auf einen Satz von Daten ausgeführt wurden. Eine Prozedur, oder auch Funktion, ist ein Satz spezifischer Anweisungen, die nacheinander ausgeführt werden. Die Daten wurden getrennt von den Prozeduren gehalten und der Trick bei der Programmierung lag darin, sich zu merken, welche Funktion welche anderen Funktionen aufrief und welche Daten geändert wurden.

Um etwas Vernünftiges aus dieser eventuell verwirrenden Situation zu machen, wurde die strukturierte Programmierung erzeugt.

Der Grundgedanke der strukturierten Programmierung läßt sich auf die Formel »teile und herrsche« bringen. Ein Computerprogramm kann man sich auch als einen Satz von Aufgaben vorstellen. Jede Aufgabe, deren Beschreibung zu komplex ist, wird in eine Menge kleinerer Teilaufgaben zerlegt. Das setzt man solange fort, bis die Teilaufgaben klein genug sind, um bequem gelöst zu werden, dabei aber noch groß genug sind, um in sich abgeschlossenen zu sein und einen vernünftigen Zweck zu erfüllen.

Zum Beispiel ist die Berechnung des Durchschnittsgehalts aller Beschäftigten einer Firma eine ziemlich komplexe Aufgabe. Man kann diese allerdings in die folgenden Teilaufgaben zerlegen:

  1. Verdienst jeder Person ermitteln.
  2. Anzahl der Beschäftigten ermitteln.
  3. Summe aller Gehälter bilden.
  4. Dividieren der ermittelten Summe durch die Anzahl der Beschäftigten.

Punkt 3 läßt sich weiter in folgende Teilaufgaben gliedern:

  1. Den Datensatz eines Beschäftigten abfragen.
  2. Auf das Gehalt zugreifen.
  3. Das Gehalt zur bisherigen Gesamtsumme addieren.
  4. Den nächsten Datensatz eines Beschäftigten abfragen.

Das Abfragen eines Beschäftigtendatensatzes kann wiederum in folgende Aufgaben unterteilt werden:

  1. Datei der Beschäftigten öffnen.
  2. Zum entsprechenden Datensatz gehen.
  3. Daten von der Festplatte lesen.

Die strukturierte Programmierung ist nach wie vor ein enorm erfolgreicher Lösungsansatz bei komplexen Aufgabenstellungen. Ende der Achtziger zeichneten sich jedoch die Schwächen der strukturierten Programmierung deutlich ab.

Zum einen ist es nur natürlich, sich die Daten (Datensätze der Beschäftigten zum Beispiel) und die Aktionen mit diesen Daten (sortieren, bearbeiten usw.) als eine Einheit vorzustellen. Die prozedurale Programmierung steht diesem entgegen, da sie die Datenstrukturen von den Funktionen, die die Daten manipulieren, trennt.

Zweitens stellten Programmierer fest, daß sie das Rad immer wieder neu erfanden, das heißt sie fanden regelmäßig neue Lösungen für alte Probleme - das Gegenteil der Wiederverwendbarkeit. Der Gedanke hinter der Wiederverwendbarkeit ist der Aufbau von Komponenten mit bekannten Eigenschaften. Diese Komponenten fügt man dann bei Bedarf in ein Programm ein. Dieses Modell entspricht der Hardware-Welt - wenn ein Techniker einen neuen Transistor benötigt, erfindet er ihn in der Regel nicht neu, sondern sucht sich aus seinen Beständen den passenden heraus und modifiziert ihn vielleicht. Für den Software-Techniker gab es keine vergleichbare Möglichkeit.

Die Art und Weise, wie wir jetzt Computer benutzen - mit Menüs und Schaltflächen und Fenstern - begünstigt einen interaktiveren, ereignisorientierten Ansatz der Computerprogrammierung. Ereignisorientiert bedeutet, daß ein Ereignis eintritt - der Benutzer drückt einen Schalter oder trifft eine Auswahl aus einem Menü - und das Programm muß reagieren. Programme werden zunehmend interaktiver und im gleichen Maße ist es wichtig, den Entwurf auf diese Art der Funktionalität auszurichten.

Veraltete Programme zwangen den Benutzer schrittweise, das heißt Bildschirm für Bildschirm, Dialog für Dialog, sich durch das Programm zu mühen. Moderne, ereignisorientierte Programme stellen alle Optionen direkt zur Verfügung und antworten auf Benutzeraktionen.

In der objektorientierten Programmierung wird versucht, auf diese Bedürfnisse einzugehen und Techniken bereitzustellen, die dieser enormen Komplexität Herr werden, die Wiederverwendbarkeit der Software-Komponenten ermöglichen und die Daten mit den Aufgaben zur Datenmanipulation verbinden.

Das Wesen der objektorientierten Programmierung besteht in der Behandlung der Daten und der Prozeduren, die auf diesen Daten arbeiten, als geschlossenes »Objekt« - eine selbständige Einheit mit einer Identität und eigenen Charakteristika.

C++ und objektorientierte Programmierung

C++ unterstützt voll die objektorientierte Programmierung (OOP), einschließlich der drei Säulen der objektorientierten Entwicklung: Kapselung, Vererbung und Polymorphie.

Kapselung

Wenn der Elektroniker einen Widerstand für ein Gerät benötigt, das er entwickeln möchte, baut er in der Regel keinen neuen, sondern sucht sich anhand der Farbetiketten, die die Eigenschaften anzeigen, den geeigneten Widerstand aus seinen Beständen heraus. Für den Elektroniker ist der Widerstand eine »Black Box« - er kümmert sich nicht speziell darum, wie der Widerstand arbeitet, solange er den Spezifikationen entspricht. Er muß nicht hinter die Funktionsweise schauen, um ihn für seinen Entwurf zu verwenden.

Die Eigenschaft, eine eigenständige Einheit zu sein, wird auch Kapselung genannt. Mit der Kapselung können Daten verborgen werden - ein hochgeschätztes Charakteristikum eines Objekts, das genutzt werden kann, ohne daß der Benutzer die internen Arbeitsabläufe kennen muß. Genauso wie Sie einen Kühlschrank benutzen können, ohne davon Ahnung haben zu müssen, wie der Kompressor funktioniert, können Sie ein gut entworfenes Objekt verwenden, ohne etwas über dessen interne Datenelemente zu wissen.

Gleichermaßen muß der Elektroniker im Falle des Widerstandes keine Ahnung vom internen Status des Widerstandes haben. Alle Eigenschaften des Widerstandes sind im Widerstand-Objekt verkapselt und nicht über die elektronische Schaltung verteilt. Einen Widerstand kann man effektiv einsetzen, ohne mit seinen internen Abläufen vertraut zu sein. Seine Daten sind in seinem Gehäuse verborgen.

C++ unterstützt die Kapselung auf dem Weg über spezielle benutzerdefinierte Typen, die sogenannten Klassen. Wie man eine Klasse erzeugt, erfahren Sie in Kapitel 6, »Klassen«. Eine einmal definierte Klasse agiert als vollständig gekapselte Einheit und wird als Ganzheit verwendet. Die eigentliche innere Funktionsweise der Klasse sollte nicht sichtbar sein. Die Benutzer einer gut konzipierten Klasse müssen nicht wissen, wie die Klasse funktioniert, sie müssen nur wissen, wie man sie verwendet.

Vererbung und Wiederverwendbarkeit

Wenn die Ingenieure bei Acme Motors ein neues Auto bauen wollen, haben Sie zwei Möglichkeiten: Sie können ein vollständig neues Modell entwickeln oder auf ein vorhandenes Modell aufbauen. So ist vielleicht Ihr Modell Star so gut wie perfekt, aber es soll jetzt eine Ausführung mit Turbolader und 6-Gang-Getriebe geben. Der Chefingenieur könnte es vorziehen, nicht ganz von vorn zu beginnen, und trifft die Entscheidung, einen neuen Star zu bauen, der um die zusätzlichen Features ergänzt wird. Und um dieses Auto vom Star-Modell abzuheben, wird es Quasar genannt. Ein Quasar ist eine Art Stern, der ganz spezielle neue Eigenschaften aufweist.

C++ unterstützt den Grundgedanken der Vererbung. Man kann einen neuen Typ deklarieren, der eine Erweiterung eines vorhandenen Typs darstellt. Man sagt, daß diese neue Unterklasse von einem vorhandenen Typ abgeleitet ist und spricht auch von einem abgeleiteten Typ. Der Quasar wird vom Star abgeleitet und erbt damit dessen gesamte Eigenschaften. Bei Bedarf kann man aber neue hinzufügen. Auf die Vererbung und ihre Anwendung in C++ gehen Kapitel 11, »Vererbung«, und Kapitel 15, »Vererbung - weiterführende Themen«, ein.

Polymorphie

Vielleicht reagiert der neue Quasar anders als ein Star, wenn Sie das Gaspedal treten. Der Quasar läuft mit Benzineinspritzung und einem Turbolader, während der Star lediglich Benzin in den Vergaser leitet. Der Fahrer muß von diesen Einzelheiten nichts wissen. Er braucht lediglich das Gaspedal »durchzutreten« und je nach Auto werden die richtigen Mechanismen in Bewegung gesetzt.

C++ unterstützt den Gedanken, daß verschiedene Objekte »genau das Richtige tun«, durch die sogenannte Funktionspolymorphie oder Klassenpolymorphie. Das aus dem Griechischen stammende Wort »polymorph« bedeutet »vielgestaltig«. Polymorphie bezieht sich also darauf, daß man einen Namen für mehrere Formen verwendet. Näheres dazu finden Sie in den Kapiteln 10, »Funktionen - weiterführende Themen«, und 13, »Polymorphie«.

Wie sich C++ entwickelt hat

Als sich die objektorientierte Methodik bei Analyse, Entwurf und Programmierung durchzusetzen begann, nahm Bjarne Stroustrup die populärste Sprache für die kommerzielle Software-Entwicklung, C, und erweiterte sie um Merkmale der objektorientierten Programmierung.

Es stimmt zwar, daß C++ eine Obermenge von C ist und daß scheinbar jedes gültige C-Programm auch ein gültiges C++-Programm ist, doch der Sprung von C zu C++ ist größer als er scheint. C++ profitierte jahrelang von der Verwandtschaft zu C, da C- Programmierer bequem auf C++ umsteigen konnten. Viele Programmierer stellten jedoch fest, daß sie für eine umfassende Nutzung aller von C++ gebotenen Möglichkeiten viel Bekanntes vergessen und neue Konzepte und Programmlösungen erlernen mußten.

Sollte ich zuerst C lernen?

Es drängt sich die Frage auf: »Soll ich zuerst C lernen, weil C++ eine Obermenge von C ist?« Stroustrup und die meisten C++-Programmierer stimmen überein: Es ist nicht nur nicht erforderlich, zuerst C zu lernen, sondern auch eine schlechte Empfehlung.

Dieses Buch geht davon aus, daß Sie kein C-Programmierer sind. Andernfalls wäre das auch kein Problem. Lesen Sie die ersten Kapitel als Wiederholung, und legen Sie sich dann richtig ins Zeug. Mit Kapitel 6, »Klassen«, steigen wir dann so richtig in die objektorientierte Programmierung ein.

C++ und Java

C++ ist heute die am weitesten verbreitete Programmiersprache, zur Erstellung kommerzieller Software entwickelt. In den letzten Jahren wurde diese Vormachtstellung durch Java bedroht, doch inzwischen schwingt das Pendel wieder zurück, und viele Programmierer, die von C++ zu Java gewechselt haben, sind inzwischen wieder auf C++ zurückgekommen. So viel läßt sich jedenfalls feststellen: Die beiden Sprachen sind sich so ähnlich, daß, wer eine Sprache beherrscht, fast 90 % der anderen damit abdeckt.

Der ANSI-Standard

Das Accredited Standards Committee, das dem American National Standards Institute (amerikanisches Normungsinstitut) unterstellt ist, hat einen internationalen Standard für C++ aufgesetzt.

Der C++-Standard wird inzwischen auch als ISO-Standard (International Standards Organization), NCITS-Standard (National Committee for Information Technology Standards), X3-Standard (alter Name für NCITS) und als ANSI/ISO-Standard bezeichnet. In diesem Buch wird vom ANSI-Standardcode gesprochen, da dies der geläufigste Begriff ist.

Der ANSI-Standard versucht sicherzustellen, daß C++ portierbar ist. Damit soll zum Beispiel garantiert werden, daß Code, der in Übereinstimmung mit dem ANSI-Standard für einen Microsoft-Compiler aufgesetzt wurde, auch ohne Fehler mit einem Compiler eines beliebigen Drittanbieters kompiliert werden kann. Da der Code dieses Buches ebenfalls dem ANSI-Standard folgt, sollten sich die Beispiele fehlerfrei auf einem Mac-, einem Windows- oder einem Alpha-PC kompilieren lassen.

Die meisten, die C++ erlernen, werden den ANSI-Standard nicht wahrnehmen. Schon seit einiger Zeit ist der ANSI-Standard recht stabil und alle größeren Hersteller unterstützen ihn. Wir haben uns bemüht, alle Codebeispiele in diesem Buch auf den ANSI-Standard hin auszurichten.

Vorbereitungen

In C++ ist wichtig, wichtiger vielleicht als in anderen Sprachen, daß der Programmierer das Programm entwirft, bevor er es niederschreibt. Triviale Probleme, wie etwa die in den ersten Kapiteln dieses Buches behandelten, erfordern kaum Entwurfsarbeit. Allerdings ist ein Entwurf bei komplexen Problemen, die die professionellen Programmierer alltäglich herausfordern, unumgänglich. Je gründlicher der Entwurf, desto wahrscheinlicher stellt das Programm für die vorgesehenen Aufgaben eine Lösung dar - sowohl im zeitlichen als auch im finanziellen Rahmen. Ein guter Entwurf führt auch zu einem relativ fehlerfreien und leicht zu wartenden Programm. Man schätzt, daß sich 90 % der Software-Kosten aus Fehlersuche und Wartung zusammensetzen. Ein guter Entwurf hat damit bedeutenden Einfluß auf die Senkung der Gesamtkosten des Projekts.

Bei der Vorbereitung auf den Programmentwurf ist zuerst die Frage zu beantworten: »Welches Problem versuche ich zu lösen?« Jedes Programm sollte ein klares, gut formuliertes Ziel besitzen. Sogar bei den einfachsten Programmen in diesem Buch begegnen Sie diesem Ansatz.

Die zweite Frage für jeden guten Programmierer ist: »Kann man das Ziel erreichen, ohne benutzerspezifische Software schreiben zu müssen?« Die Wiederverwendung und Anpassung vorhandener Programme oder der Kauf von konfektionierter Software sind oft bessere Lösungen für ein Problem als etwas Neues zu schreiben. Der Programmierer, der diese Alternativen zu bieten hat, wird niemals arbeitslos; durch die Entwicklung kostengünstiger Lösungen für aktuelle Probleme ergeben sich fast immer neue Möglichkeiten für die Zukunft.

Hat man das Problem erfaßt und ist das Schreiben eines neuen Programms unumgänglich, kann man mit dem Entwurf beginnen.

Der Prozeß, das Problem voll zu erfassen (Analyse) und mit einer Lösung (Entwurf) aufzuwarten, ist die notwendige Grundlage, um eine kommerzielle Anwendung von Weltklasse zu schreiben.

Doch auch wenn die Schritte, das Problem zu erfassen und eine Lösung zu entwerfen, vor dem eigentlichen Aufsetzen des Codes stehen, ist es ratsamer, sich mit der grundlegenden Syntax und Semantik von C++ vertraut zu machen, bevor man sich den formalen Analyse- und Entwurfstechniken widmet.

Ihre Entwicklungsumgebung

Dieses Buch geht von der Annahme aus, daß Ihr Compiler über einen Modus verfügt, mit dem man direkt auf den Bildschirm schreiben kann, ohne erst lang Gedanken an eine Graphik-Umgebung wie in Windows oder auf dem Macintosh zu verlieren. Halten Sie Ausschau nach einer Option wie Konsolen- oder Textbildschirmanwendung, oder schauen Sie in Ihren Compiler-Handbüchern nach.

Möglicherweise verfügt Ihr Compiler über einen eigenen Editor, oder Sie verwenden einen kommerziellen Texteditor oder eine Textverarbeitung, die Textdateien erzeugen kann. Mit welchem Werkzeug Sie Ihr Programm auch erstellen, es muß reine Textdateien ohne eingebettete Steuerbefehle liefern. Beispiele für »sichere« Editoren sind der zu Windows gehörende Editor Notepad, der über den DOS-Befehl Edit aufrufbare Editor, Brief, Epsilon, EMACS und vi. Kommerzielle Textverarbeitungen wie WordPerfect, Word und Dutzende andere bieten ebenfalls die Möglichkeit, das Dokument als einfache Textdatei zu speichern.

Die Dateien, die Sie mit Ihrem Editor erstellen, bezeichnet man als Quelldateien. Normalerweise erhalten diese Dateien unter C++ die Dateierweiterung .CPP, .CP oder .C. In diesem Buch sind alle Quellcodedateien einheitlich mit der Erweiterung .CPP versehen. Prüfen Sie bitte, welche Erweiterungen Ihr Compiler benötigt.

Bei den meisten C++-Compilern hat die Erweiterung der Quelldateien keine besondere Bedeutung. Gibt man allerdings keine Erweiterung explizit an, verwenden viele Compiler per Vorgabe die Erweiterung .CPP. Seien Sie jedoch mit der Verwendung .C vorsichtig, da einige Compiler davon ausgehen, daß es sich bei .C-Dateien um C-Code und bei .CPP-Dateien um C++ handelt. Auch hier möchte ich Ihnen nahelegen, einen Blick in Ihre Handbücher zu werfen.

Was Sie tun sollten

... und was nicht

Erstellen Sie den Quellcode mit einem einfachen Texteditor, oder arbeiten Sie mit dem Editor, der zum Compiler gehört.

Speichern Sie Ihre Dateien mit den Erweiterungen .C, .CP oder .CPP.

Machen Sie sich anhand der Dokumentation mit den Eigenheiten Ihres Compilers und Linkers vertraut, damit Sie wissen, wie Programme zu kompilieren und zu linken sind.

Verwenden Sie keine Textverarbeitung, die spezielle Formatierungszeichen speichert. Sollten Sie doch mit einer Textverarbeitung arbeiten, speichern Sie die Datei als ASCII- Text.

Quellcode kompilieren

Obwohl der Quellcode in Ihrer Datei etwas kryptisch aussieht und jeder, der sich mit C++ nicht auskennt, kaum versteht, für was das ganze gut ist, haben wir es trotzdem mit einer für den Menschen verständlichen Form zu tun. Die Quellcodedatei ist kein Programm und läßt sich auch nicht wie ein Programm ausführen.

Um aus dem Quellcode ein Programm zu machen, verwendet man einen Compiler. Wie man den Compiler aufruft und ihm den Standort der Quelldatei angibt, ist vom konkreten Compiler abhängig. Sehen Sie dazu in der entsprechenden Dokumentation nach.

Durch das Kompilieren des Quellcodes entsteht eine sogenannte Objektdatei (in der Regel mit der Erweiterung .OBJ). Allerdings handelt es sich auch hier noch nicht um ein ausführbares Programm. Um aus der Objektdatei ein ausführbares Programm zu erstellen, ruft man den Linker auf.

Ein ausführbares Programm mit dem Linker erstellen

C++-Programme werden in der Regel durch das Verbinden (Linken) einer oder mehrerer Objektdateien mit einer oder mehreren Bibliotheken erzeugt. Unter einer Bibliothek versteht man eine Sammlung von Dateien, die vom Linker direkt in ein Programm mit eingebunden werden können. Bibliotheken erwirbt man automatisch zusammen mit dem Compiler, man kauft sie extra dazu oder man erzeugt und kompiliert sie selbst. Zu allen C++-Compilern gehört eine Bibliothek nützlicher Funktionen und Klassen, die Sie in Ihr Programm aufnehmen können. Eine Funktion ist ein Codeblock, der eine bestimmte Aufgabe realisiert, beispielsweise das Addieren zweier Zahlen oder die Ausgabe auf den Bildschirm. Unter einer Klasse versteht man eine Sammlung von Daten und verwandten Funktionen. Auf Funktionen und Klassen gehen wir ab Kapitel 5 noch näher ein.

Eine ausführbare Datei erzeugt man in folgenden Schritten:

  1. Erstellen einer Quellcodedatei mit der Erweiterung .CPP.
  2. Kompilieren der Quellcodedatei in eine Objektdatei mit der Erweiterung .OBJ.
  3. Linken der Objektdatei mit allen erforderlichen Bibliotheken zu einem ausführbaren Programm.

Der Entwicklungszyklus

Wenn jedes Programm sofort beim ersten Ausprobieren funktionieren würde, hätten wir es mit folgendem vollständigen Entwicklungszyklus zu tun: Schreiben des Programms, Kompilieren des Quellcodes, Linken des Programms und Ausführen des Programms. Leider enthält fast jedes Programm irgendwelche Fehler - sogenannte Bugs - auch wenn sie manchmal nur trivial sind. Einige Bugs verhindern bereits das Kompilieren, bei manchen Fehlern kann man das Programm nicht linken, und einige Fehler zeigen sich erst bei der Ausführung des Programms.

Welchen Fehler Sie auch finden, er ist zu beseitigen. Und dazu gehört die Bearbeitung des Quellcodes, das erneute Kompilieren und Linken und schließlich ein neuer Start des Programms. Abbildung 1.1 zeigt diesen Zyklus mit einer Darstellung der einzelnen Schritte.

Abbildung 1.1:  Die Schritte im Entwicklungsprozeß  eines C++-Programms

HELLO.CPP - Ihr erstes C++-Programm

Es ist schon Tradition, daß ein Programmierbuch mit einem Programm beginnt, das die Worte Hello World auf den Bildschirm bringt oder eine ähnliche Aufgabe realisiert. Auch wir bleiben dieser Tradition treu.

Tippen Sie das erste Programm direkt in Ihren Editor - genau wie dargestellt - ein. Nachdem Sie den Quellcode kritisch durchgesehen haben, speichern Sie die Datei, kompilieren sie, linken sie und führen sie aus. Auf dem Bildschirm erscheinen die Worte Hello World. Kümmern Sie sich momentan noch nicht darum, wie das Ganze funktioniert, das Programm soll Sie nur mit dem Entwicklungszyklus vertraut machen. Die einzelnen Aspekte dieses Programms sind Gegenstand der nächsten Lektionen.

Das folgende Listing enthält an der linken Seite Zeilennummern. Diese dienen lediglich der Bezugnahme in diesem Buch und sind nicht als Teil des Quellcodes im Editor einzugeben. Beispielsweise geben Sie die Zeile 1 von Listing 1.1 in der folgenden Form ein:

#include <iostream.h>

Listing 1.1: HELLO.CPP, das Programm Hello World

1:  #include <iostream.h>
2:
3: int main()
4: {
5: cout << "Hello World!\n";
6: return 0;
7: }

Vergewissern Sie sich, daß alles exakt wie dargestellt eingegeben wurde. Achten Sie insbesondere auf die Satzzeichen. Das Symbol << in Zeile 5 ist ein Umleitungssymbol, das man auf deutschen Tastaturen rechts neben der linken Umschalt-Taste findet. Zeile 5 endet mit einem Semikolon, das auf keinen Fall fehlen darf!

Prüfen Sie auch, ob die Compiler-Direktiven entsprechend eingestellt sind. Die meisten Compiler linken automatisch. Trotzdem sollten Sie in der Dokumentation nachsehen. Wenn Sie Fehler erhalten, überprüfen Sie zunächst sorgfältig den eingegebenen Code und suchen nach Abweichungen von Listing 1.1. Wenn Sie einen Fehler zu Zeile 1 erhalten, wie etwa Include-Datei kann nicht geoeffnet werden: 'iostream.h'... , sollten Sie sich in der Dokumentation zu Ihrem Compiler über die Einstellungen für den Include-Pfad und die Umgebungsvariablen informieren. Wenn Sie einen Fehler erhalten, daß es keinen Prototyp für main gibt, fügen Sie die Zeile int main(); unmittelbar vor Zeile 3 ein. Diese Zeile müssen Sie jedem Programm in diesem Buch vor Beginn der Funktion main() hinzufügen. Viele Compiler kommen ohne aus, bei einigen aber ist es erforderlich.

Das fertige Programm sieht folgendermaßen aus:

1:  #include <iostream.h>
2: int main(); // die meisten Compiler kommen ohne
3: // diese Zeile aus
4: int main() {
5: {
6: cout << "Hello World!\n";
7: return 0;
8: }

Führen Sie nun Hello.exe aus. Auf dem Bildschirm sollte der Text

Hello World!

erscheinen. Sollte das so sein, Gratulation! Sie haben gerade Ihr erstes C++-Programm eingegeben, kompiliert und ausgeführt. Es ist vielleicht nicht gerade berauschend, aber nahezu jeder professionelle C++-Programmierer hat genau mit diesem Programm begonnen.

Einsatz der Standardbibliotheken

Um sicherzustellen, daß Leser mit älteren Compilern keine Schwierigkeiten mit dem Code dieses Buches haben, verwenden wir die älteren include-Dateien. So finden Sie

#include <iostream.h>

anstelle der neuen Header-Dateien der Standardbibliotheken

#include <iostream>

Dies sollte auf allen Compilern funktionieren und hat nur geringfügige Nachteile. Ziehen Sie es jedoch vor, die Bibliotheken des neuen Standards zu verwenden, ändern Sie Ihren Code einfach in

#include <iostream>

und fügen Sie die Zeile

using namespace std;

direkt unter Ihre Liste der include-Dateien. Das weiterführende Thema der Namensbereiche wird noch eingehender in Kapitel 17 besprochen.

Ob Sie jetzt Standard-Headerdateien verwenden oder nicht, sollte die Ausführung des Codes in diesem Buch eigentlich nicht betreffen. Der wichtigste Unterschied zwischen den älteren Bibliotheken und der neuen Standardbibliothek ist die iostream-Bibliothek (die Beschreibung finden Sie in Kapitel 16). Doch auch diese Änderungen haben keinen Einfluß auf den Code in diesem Buch. Die Änderungen sind nur geringfügig und nur für Eingeweihte; zumindest gehen Sie weit über den Rahmen eines Anfängerhandbuchs hinaus.

Die ersten Schritte mit Visual C++ 6

Alle Programme dieses Buchs wurden mit dem Visual C++ 6-Compiler getestet und sollten sich mit allen Visual C++-Compilern von Microsoft ab 4.0 und höher problemlos kompilieren, linken und ausführen lassen. Theoretisch sollten sich die Programme dieses Buchs, da der Code dem ANSI-Standard entspricht, auf allen Compilern auf dem Markt ausführen lassen.

In der Theorie sind Theorie und Praxis eins. In der Praxis jedoch nie.

Für Ihre ersten Schritte soll Sie dieser kurze Abschnitt darin einführen, wie Sie ein Programm mit dem Microsoft-Compiler bearbeiten, kompilieren, linken und ausführen. Wenn Sie einen anderen Compiler verwenden, können die Schritte leicht von den hier beschriebenen abweichen. Aber auch wenn Sie Microsofts Visual C++ 6- Compiler benutzen, lesen Sie in Ihrer Dokumentation nach, wie Ihre Schritte ab hier aussehen.

Das Hello World-Projekt erstellen

Gehen Sie wie folgt vor, um das Programm Hello World zu erstellen und zu testen:

  1. Starten Sie den Compiler.
  2. Rufen Sie den Menübefehl Datei/Neu auf.
  3. Wählen Sie Win32-Konsolenanwendung und geben Sie einen Projektnamen wie Beispiel1 ein. Klicken Sie dann auf OK.
  4. Aktivieren Sie die Option Ein leeres Projekt und klicken Sie auf Fertigstellen.
  5. Rufen Sie den Menübefehl Datei/Neu auf.
  6. Wählen Sie C++-Quellcodedatei und nennen Sie die Datei bsp1.
  7. Geben Sie den Code wie oben abgedruckt ein.
  8. Rufen Sie Erstellen/Beispiel1.exe erstellen auf.
  9. Prüfen Sie, ob beim Kompilieren keine Fehler auftauchen.
  10. Drücken Sie STRG+F5, um das Programm auszuführen.
  11. Drücken Sie die Leertaste, um das Programm zu beenden.

Fehler zur Kompilierzeit

Fehler zur Kompilierzeit können verschiedenste Ursachen haben. Gewöhnlich sind sie das Ergebnis eines Schreibfehlers oder einer anderen Nachlässigkeit. Gute Compiler weisen nicht nur darauf hin, was Sie falsch gemacht haben, sie zeigen genau die Stelle im Code an, wo der Fehler aufgetreten ist. Die besten Compiler schlagen sogar eine Lösung vor!

Einen Compiler-Fehler können Sie sich in der Praxis ansehen, indem Sie absichtlich einen Fehler in das Programm einbauen. Nachdem Sie Hello.cpp erst einmal richtig zum Laufen gebracht haben, bearbeiten Sie nun die Quelldatei und entfernen die schließende Klammer auf Zeile 7. Das Programm entspricht nun Listing 1.2.

Listing 1.2: Demonstration eines Compiler-Fehlers

1:  #include <iostream.h>
2:
3: int main()
4: {
5: cout << "Hello World!\n";
6: return 0;

Kompilieren Sie Ihr Programm erneut. Es sollte nun die folgende Fehlermeldung erscheinen:

****Hello.cpp, line 5: Compound statement missing terminating } 
in function main().

oder auch:

F:\Mcp\Tycpp21d\Testing\List0101.cpp(8) : fatal error C1004:
unexpected end of file found
Error executing cl.exe.
}

Diese Fehlermeldung teilt Ihnen die problematische Datei und die Zeilennummer mit und um welches Problem es sich handelt. (Zugegebenermaßen sieht das ganze etwas kryptisch aus.) Beachten Sie, daß die Fehlermeldung auf Zeile 5 verweist. Der Compiler war sich nicht sicher, ob Sie die schließende Klammer vor oder nach der cout-Anweisung in Zeile 5 setzen möchten. Manchmal bezieht sich die Fehlermeldung auf die unmittelbare Nachbarschaft des Problems. Könnte ein Compiler jedes Problem perfekt identifizieren, könnte er den Code auch selbst von Fehlern bereinigen.

Zusammenfassung

Nach dem Studium dieses Kapitels sollten Sie einen Überblick haben, wie sich C++ entwickelt hat und für welche Art von Problemlösungen diese Sprache geschaffen wurde. Sie sollten sich bestärkt fühlen, daß das Erlernen von C++ die richtige Wahl für jeden an der Programmierung Interessierten im nächsten Jahrzehnt ist. C++ stellt die Werkzeuge der objektorientierten Programmierung und die Leistung einer systemnahen Sprache zur Verfügung, was C++ zur bevorzugten Entwicklungssprache macht.

In diesem ganz am Anfang stehenden Kapitel haben Sie gelernt, wie Sie Ihr erstes C++-Programm schreiben, kompilieren, linken und ausführen, und wie der normale Entwicklungszyklus aussieht. Außerdem haben Sie sich ein wenig mit dem Grundanliegen der objektorientierten Programmierung vertraut gemacht. Zu diesen Themen kehren Sie während der restlichen Unterrichtsstunden zurück.

Fragen und Antworten

Frage:
Worin besteht der Unterschied zwischen einem Texteditor und einer Textverarbeitung?

Antwort:
Ein Texteditor erzeugt Dateien, die aus reinem Text bestehen und keinerlei Formatierungsbefehle oder andere spezielle Symbole, wie sie für eine Textverarbeitung erforderlich sind, enthalten. Bei reinen Textdateien gibt es keinen automatischen Zeilenumbruch, keinen Fettdruck, keine kursive Zeichen usw.

Frage:
Mein Compiler verfügt über einen integrierten Editor. Ist das das geeignete Werkzeug?

Antwort:
Fast alle Compiler sind in der Lage, den von beliebigen Texteditoren erzeugten Code zu kompilieren. Der Vorteil des integrierten Editors besteht allerdings darin, daß man gegebenenfalls schnell zwischen den Entwicklungsschritten Editieren und Kompilieren hin- und herschalten kann. Zu modernen Compilern gehört eine integrierte Entwicklungsumgebung, die dem Programmierer den Zugriff auf Hilfedateien, die Bearbeitung und das Kompilieren des Codes unmittelbar erlaubt. Außerdem lassen sich hier Compiler- und Linker- Fehler beseitigen, ohne daß man die Umgebung verlassen muß.

Frage:
Kann ich Warnungen des Compilers ignorieren?

Antwort:
Auf keinen Fall. Machen Sie es sich zur Angewohnheit, Warnungen als Fehler zu behandeln. C++ verwendet den Compiler, um Sie vor etwas zu warnen, das Sie möglicherweise gar nicht beabsichtigen. Unternehmen Sie die erforderlichen Schritte, damit diese Warnungen nicht wieder auftreten.

Frage:
Was versteht man unter der Kompilierzeit?

Antwort:
Die Kompilierzeit ist die Phase im Entwicklungszyklus, zu der man den Compiler ausführt. Weitere Phasen sind die Linkzeit (wenn man den Objektcode mit dem Linker verknüpft) oder die Laufzeit (wenn man das Programm ausführt). Damit differenziert der Programmierer die drei Zeitabschnitte, in denen Fehler normalerweise zutage treten.

Workshop

Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, und Übungen, die Sie anregen sollen, das eben Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Versuchen Sie, das Quiz und die Übungen zu beantworten und zu verstehen, bevor Sie die Lösungen in Anhang D lesen und zur Lektion des nächsten Tages übergehen.

Quiz

  1. Was ist der Unterschied zwischen einem Interpreter und einem Compiler?
  2. Wie kompilieren Sie den Quellcode mit Ihrem Compiler?
  3. Welche Aufgabe obliegt dem Linker?
  4. Wie lauten die Schritte in einem normalen Entwicklungszyklus?

Übungen

  1. Betrachten Sie das folgende Programm und raten Sie, was es macht, ohne es auszuführen.
    1: #include <iostream.h>
    2: int main()
    3: {
    4: int x = 5;
    5: int y = 7;
    6: cout << "\n";
    7: cout << x + y << " " << x * y;
    8: cout << "\n";
    9: return 0;
    10:}
  2. Tippen Sie das Programm von Übung 1 ein und kompilieren und linken Sie es anschließend. Was macht das Programm? Stimmt das mit Ihrer Annahme überein?
  3. Tippen Sie das folgende Programm ein und kompilieren Sie es. Welche Fehlermeldung erhalten Sie?
    1: include <iostream.h>
    2: int main()
    3: {
    4: cout << "Hello World\n";
    5: return 0;
    6: }
  4. Beheben Sie den Fehler im Programm aus Übung 3. Kompilieren, linken und starten Sie es. Was macht das Programm?



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


© Markt&Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH