Nach insgesamt 8
Jahren intensiver Bemühung ist die Sprache C++ nun endlich standardisiert. Das
entsprechende Dokument (kurz „der Standard“ genannt) ist immerhin 748 Seiten
stark und beschreibt die Syntax und Semantik der Sprache so präzise, dass
nahezu kein Spielraum mehr für Streitfragen existiert.
Allerdings ist der
Standard auch für einen erfahrenen Programmierer über weite Strecken schlichtweg
unlesbar. Zu kompliziert sind die Formulierungen, zu schwierig die Details, zu
ausgefallen manche Beispiele. Dies ist der Preis, der für eine genaue Definition der Syntax und Semantik der
Sprache zu bezahlen ist. Während der „normale“ Sprachgebrauch noch relativ einfach
zu beschreiben ist, muss das Standarddokument mehr leisten: Zu jedem denkbaren
Programm muss anhand des Standards entschieden werden können, ob es syntaktisch
zulässig ist, oder nicht. Ist es syntaktisch korrekt, muss der Standard auch
eindeutige Aussagen über das Verhalten
(die sog. Semantik) des Programms
definieren. Für eine so mächtige Sprache wie
C++ keine einfache Aufgabe.
Das
Standarddokument ist daher für die Praxis der Programmierung denkbar
ungeeignet. Was nützt es, wenn eine Konstruktion vielleicht zwar syntaktisch
korrekt ist, von den gängigen Compilern jedoch (noch) nicht unterstützt wird? Für die Praxis benötigt man andere
Referenzen, die unter anderem auch den heutigen Stand der Compilertechnik berücksichtigen.
&& Inhalt
Dieses Buch
beschreibt die Aspekte, die für die erfolgreiche Entwicklung von Programmen
mit Hilfe von C++ wichtig sind, und zwar sowohl für das Design als auch für
die Implementierung. Besonderes Augenmerk wird dabei auf die
Objektorientierung gelegt, für die C++ ganz ausgezeichnete Sprachmittel
bereitstellt.
C++ ist jedoch
keine rein objektorientierte Sprache, sondern lässt ganz explizit auch andere
Programmierstile zu. Neben der objektorientierten
Programmierung streifen wir die prozedurale
Programmierung, wie sie in traditionellen Sprachen wie z.B. C üblich ist,
und werfen einen Blick auf die funktionale
Programmierung, die durch das mächtige Sprachmittel der Schablonen (Templates) in C++ möglich geworden ist.
Das insgesamt
verfügbare Material über die Softwareentwicklung mit C++ ist für ein einziges
Buch zu umfangreich. Es war daher sinnvoll, eine Zweiteilung vorzunehmen:
q In dem hier
vorliegenden Buch mit dem Titel Die Kunst
der Programmierung mit C++ konzentrieren wir uns auf die Syntax und
Semantik der Sprache. Hier werden die Sprachmittel vorgestellt, die C++ für
den Programmierer bereithält. Dabei wechseln sich theoretische Kapitel mit
praktischen Fallstudien ab: In den theoretischen Kapiteln werden jeweils
neue Sprachkonstruktionen vorgestellt, die dann im nachfolgenden Praxiskapitel
sofort an konkreten Problemstellungen angewendet werden. Parallel dazu gibt
es ein Projekt (d.h. eine vollständig ausgearbeitete Aufgabe), das in den
einzelnen Kapiteln ständig weiter entwickelt wird und am Ende des Buches in
einer professionellen Lösung vorliegt. Zu jedem Thema gibt es darüber hinaus
Übungen. Die Musterlösungen des Autors finden sich auf der Internet-Seite des
Buches.
q In einem
weiteren Buch mit dem Titel Die fortgeschrittene
Kunst der Programmierung mit C++ betrachten wir Themen, die vor allem
beim Einsatz von C++ bei der professionellen Programmierung in großen Projekten
zum Tragen kommen. Einsatz der C++-Standardbibliothek, Entwurfsmuster, Beherrschung
von Komplexität, Kontraktorientiertes Programmieren, Zusammenarbeit mit anderen
Programmiersprachen, Techniken zum Fehlermanagement und nicht zuletzt Stil und
Formfragen bei der Programmierung sind nur einige Themen, die dort behandelt
werden. Die Beherrschung der Sprache an sich wird dabei vorausgesetzt.
Das vorliegende Buch besteht aus zwei Teilen:
q Teil I: Die Grundlagen. Im ersten Teil werden die
Sprachmittel der Sprache C++ vorgestellt, die wohl in jeder der bekannten Programmiersprachen
irgendwie vorhanden sind: Zahlen, Zeichen, Zeichenketten, Arithmetik, Deklarationen
und Definitionen, Aggregationen, Verweise, Funktionen. Da diese C++ -
Sprachmittel nahezu identisch von der Sprache C übernommen wurden, bietet
dieser Teil dem erfahrenen Programmierer wahrscheinlich viel Bekanntes. Der
Teil I zeigt, dass C++ nicht nur eine objektorientierte Programmiersprache ist,
sondern auch eine Sprache, in der man klassisch funktional und bei Bedarf auch
maschinennah (hier im Gegensatz zu plattformunabhängig gesehen) programmieren
kann.
q Teil II: Das Richtige
C++. Dies ist
der Hauptteil des Buches. Hier werden zuallererst einmal die Sprachmittel
beschrieben, die zur Definition und Implementierung von objektorientierten Abstraktionen
bereitstehen. Dazu gehören vor allem Klassen, Objekte, Vererbung sowie
Sprachmittel zur Realisierung des Polymorphismus,
der in allen objektorientierten Sprachen eine zentrale Rolle einnimmt.
q C++ ist eine
der wenigen Sprachen, die einen Mechanismus wie Schablonen (templates)
unterstützt. Dadurch können Abläufe unabhängig vom Typ der betroffenen Werte
formuliert werden. Eine der Hauptanwendungen für Schablonen sind sicherlich
Container, die mit ihrer Hilfe typsicher formuliert werden können. Darüber
hinaus ermöglichen Schablonen Techniken, die bis dahin undenkbar waren, und
die auch heute noch Gegenstand heißer Diskussionen sogar unter Fachleuten
sind. Schablonen sind im Standard erst relativ spät exakt definiert worden, die
heutigen Compiler haben auch hier noch die meisten Defizite.
q Zu den
fortgeschritteneren Sprachmitteln gehört auch das Thema Fehlerbehandlung mit Ausnahmen (exceptions). Dinge wie Überladen von Operatoren, Referenztypen
sowie einige andere, weniger spektakuläre Sprachmittel, die das Abstraktionskonzept
abrunden, werden ebenfalls hier behandelt.
&& Schwerpunkt
Der Schwerpunkt
dieses Buches liegt auf der angemessenen Vorgehensweise bei der
Softwareentwicklung. Die zentrale Frage lautet:
Wie setze ich eine
gegebene Problemstellung in ein C++ Programm um?
Dabei ist hier
nicht nur die Funktionalität alleine gemeint, wie es leider von so vielen
Entwicklern in der Praxis verstanden wird: selbstverständlich muss das Programm
korrekt arbeiten, es muss genau das Problem lösen, für das es geschrieben
wurde.
Korrektheit ist jedoch nur eine Eigenschaft eines
Programms. Unter kommerziellen Gesichtspunkten ebenfalls wichtig sind aber auch
Eigenschaften wie z.B. Erweiterbarkeit, Wartbarkeit, Fehlertoleranz, Robustheit,
Verständlichkeit oder auch Kosteneffizienz bei der Erstellung, um nur einige
wichtige zu nennen. Gerade diese Eigenschaften werden neben der eigentlichen
Funktionalität von Software immer wichtiger. Sie sind es, die gute von normaler oder sogar schlechter
Software unterscheiden.
Zu einer gegebenen
Problemstellung sind viele Lösungen möglich, die unterschiedliche Ausprägungen
der gerade genannten Merkmale besitzen. Die Frage, die die Spreu von Weizen
trennt, ist letztendlich
Wie erreiche ich
zu einer gegebenen Problemstellung ein qualitativ hochwertiges Programm?
Zur Beantwortung
dieser Frage muss man einerseits die zur Verfügung stehenden Sprachmittel der
Sprache C++ genau kennen, zum andern aber auch die Vorgehensweisen beherrschen,
die bei der Umsetzung eines Problems in ein „gutes“ Programm Anwendung finden.
Vor allem der zweite Punkt wird oft vergessen. Gerade C++ Einsteiger verwenden
die komplexen und mächtigen Sprachmittel der Sprache viel zu ausgiebig und
darüber hinaus (im Sinne professioneller Programmierung) oftmals falsch. Die unüberlegte
Verwendung von mächtigen C++ Konstruktionen führt dann schnell zu unwartbaren
oder sogar fehlerhaften Programmen. Es ist genau dieser Punkt, der bei vielen
(auch erfahrenen) Umsteigern, die sich mit C++ versucht haben, im Endeffekt zu
Ablehnung führt. Die Komplexität der Programme, die mit C++ möglich sind, ist
auch einer der Gründe, warum die Sprache Java von einigen Entwicklern als „das
bessere C++“ bezeichnet wird.
Die Wurzeln der
Sprache C++ liegen in der Programmiersprache C. C++ ist syntaktisch und
semantisch (bis auf wenige Ausnahmen) eine Obermenge von C. Das bedeutet z.B.,
dass ein „ordentliches“ C Programm auch mit einem C++ Compiler übersetzt
werden kann. Von daher sind die in C vorhandenen Sprachmittel auch in C++
nahezu vollständig vorhanden. Das bedeutet jedoch auch, dass C++ einige der Unschönheiten
und Probleme der Sprache C besitzt. Hätte man sie Sprache ohne Rücksicht auf C
neu entworfen, wären sicherlich einige Dinge anders gelöst.
Die Kompatibilität
zu C war eines der wesentlichen Entwurfskriterien der Sprache C++, konnte doch
dadurch sichergestellt werden, dass die neue Sprache sofort in der
industriellen Softwareentwicklung Anwendung finden und das dort gebräuchliche
C nach und nach verdrängen konnte. Die in C bewanderten Programmierer konnten
sofort die C++ - Vorteile verwenden, ohne eine komplett neue Sprache lernen zu
müssen. Nach und nach konnten dann die leistungsfähigeren neuen Sprachmittel
dazugenommen werden – ein Bruch mit erzwungenem Neuanfang wie bei der Umstellung
auf eine komplett andere Programmiersprache konnte somit vermieden werden. Auch
heute ist C++ noch kompatibel mit C, d.h. in korrektem C geschriebene Programmteile
können (mit einigen kleinen Ausnahmen) problemlos in einem C++ Programm
verwendet werden. Dadurch können Investitionen in C-Bibliotheken (z.B.
Datenbankanbindung, Numerik) auch nach einem Umstieg auf C++ weiter verwendet
werden. Diese Eigenschaften der Sprache C++ haben sicherlich wesentlich dazu
beigetragen, dass C++ eine so weitgehende Verbreitung in der industriellen
Datenverarbeitung gefunden hat.
C++ bietet
zusätzlich neue und wesentlich andere Sprachmittel als C. Deshalb sind mit C++
andere Programmiertechniken möglich. Dinge wie Kapselung, Ableitungen oder
Polymorphismus sind in C nicht vorhanden, sondern können höchstens mühsam simuliert
werden. Eine Bibliothek mit Containern und vorgefertigten Algorithmen gehört
nicht zu C, sondern muss bei Bedarf hinzugekauft oder selbst entwickelt
werden.
In diesen
Zusammenhang wird folgende Frage häufig gestellt: Soll man C lernen, bevor man
sich mit C++ befasst? Die Antwort ist
ein klares NEIN! C++ ist zwar syntaktisch
eine Obermenge von C, damit sind die Gemeinsamkeiten jedoch schon erschöpft.
C++ ermöglicht ganz andere und bessere Programmiertechniken als C, wie wir in
diesem Buch sehen werden.
&& C++
und Java
Es wird oft
behauptet, dass Java das bessere C++ sei. Java ist „vollständig objektorientiert“, einfacher als C++ und trotzdem
genauso mächtig – und vor allem: plattformunabhängig. Java besitzt automatische
Speicherbereinigung (garbage collection),
Introspection und die Programme können in Browsern laufen. Darüber hinaus gibt
es mehr Bibliotheken als für C++. Die Verfechter der Sprache begründen mit
diesen Argumenten, dass Java grundsätzlich
besser als C++ sei.
Was sie jedoch
nicht erwähnen ist, dass Java im Vergleich mit C++ wesentliche Schwächen im
Sprachdesign und in der Laufzeitbibliothek hat. Die Einfachheit der Sprache
wird mit eingeschränkten Ausdrucksmöglichkeiten erkauft.
Man kann deshalb
nicht sagen, dass Java oder C++ generell
die bessere Sprache sei, sondern nur, dass für eine gegebene Aufgabenstellung wahrscheinlich Java oder C++ die
besseren Implementierungsmöglichkeiten bieten wird. Benötigt man unbedingt die
Ablauffähigkeit in einem Browser, führt derzeit wohl oft kein Weg an Java
(oder in Zukunft verstärkt an der .NET-Architektur) vorbei. Doch bereits beim Thema garbage
collection kann Java höchstens noch als plus verbuchen, dass diese Technik dort
bereits standardmäßig vorhanden ist, während ein collector für C++ zusätzlich
hinzugenommen werden muss. Das Fehlen einer automatischen
Speicherverwaltung in C++ wird von vielen sogar als Vorteil gesehen: Sie kostet
Ressourcen, die man z.B. in einem zeitkritischen System nicht investieren will.
Durch den Einsatz bestimmter Sprachmittel, die Java nicht, sehr wohl aber C++
besitzt, kann außerdem die Notwendigkeit einer automatischen Speicherbereinigung
sogar vollständig wegfallen. Ein Java-Anwender hat hier keine Wahl, ein C++
Anwender schon.
Das Thema „C++ vs.
Java“ wird auf jedem Seminar, in den Pausen jeder Schulungsveranstaltung und natürlich
auch im Internet kontrovers diskutiert. Meist handelt es sich um persönliche
Meinungen, teilweise werden auch Erfahrungen bei einem konkreten Projekt
veröffentlicht, selten jedoch findet man eine Analyse, warum dieses oder jenes
Sprachmittel prinzipiell gut oder schlecht ist. Dieser Unterschied zwischen
gemachter Erfahrung in einem konkreten
Projekt und prinzipieller Eignung
einer Sprache zur industriellen Softwareentwicklung ist wichtig, wird aber
allzu oft nicht beachtet.
Wir gehen in
diesem Buch auf den Sprachenstreit nicht weiter ein. An Stellen, an denen sich
die Java-Philosophie von der C++-Philosophie unterscheidet, betrachten wir
allerdings beide Seiten. Damit hat der Leser die Möglichkeit, für seine
konkrete Aufgabenstellung die geeignete Sprache zu wählen.
&& C++
und C#
Der neue Stern am
Sprachenhimmel ist sicherlich C#. Der Name „C-Sharp“ soll dabei ausdrücken,
dass die Sprache einen „Halbton“ über C liegt. C# ist vom Design her eine
Java-ähnliche Sprache, mit automatischer Speicherbereinigung etc. C# ist jedoch
auf die Microsoft-Welt zugeschnitten und ist Teil der .NET
Entwicklungsplattform. Die Sprache enthält spezielle Konstruktionen zur
Bedienung von Microsoft-Schnittstellen (wie z.B. delegates). C# vermeidet einige der schlimmsten Nachteile von Java
(z.B. fehlende Destruktoren) und kann sich so zu einer
interessanten Alternative zu Java entwickeln.
Wahrscheinlicher
jedoch wird die Zukunft von C++, Java und C# mehr durch politische als durch
sachliche oder technische Argumente bestimmt. Ein wichtiges Argument ist in
diesem Zusammenhang, dass .NET offengelegt ist und es somit anderen Firmen als
Microsoft möglich ist, eigene Implementierungen auf den Markt zu bringen. So
wird .NET derzeit für UNIX implementiert, eine Open-Source Implementierung ist
angedacht. Demgegenüber ist Java eine proprietäre Sprache, für die es nur einen
Anbieter gibt (Fa. SUN), der keine weiteren Anbieter neben sich zulässt.
Allerdings sind die wesentlichen Spezifikationen der Sprache sowie der Java
Virtual Machine auch hier öffentlich zugänglich. Die Sprache ist nicht
standardisiert, sondern sozusagen „Eigentum“ von SUN. An eine Standardisierung
(d.h. an die Übergabe der Sprache an ein Standardisierungsgremium (wie z.B.
ANSI oder ISO) ist nicht gedacht. Es ist zu erwarten, dass diese proprietäre
Politik von der Industrie nicht auf Dauer akzeptiert werden wird.
&& Sprache
und Bibliothek
Wie jede moderne
Sprache besitzt auch C++ eine Bibliothek zur Laufzeitunterstützung. Syntax und
Semantik dieser C++ Standardbibliothek sind
im C++-Standard genauestens festgelegt. Dabei ist wichtig, dass zwar das
Verhalten einer Funktion, Klasse etc. (Semantik)
definiert ist, nicht jedoch die Implementierung. Compilerhersteller sind daher
frei, ihre Implementierung beliebig zu wählen, solange die vom Standard
gesetzten Anforderungen erfüllt werden. Diese sind jedoch oft so detailliert,
dass in der Praxis nur Implementierungen mit marginalen Unterschieden zu
finden sind.
&& Compilerversionen
In diesem Buch behandeln wir
hauptsächlich Standard-C++, d.h. die
Sprache in der Form, wie sie im Standard definiert ist. Standard-C++ ist
unabhängig von einem bestimmten Compiler oder Hersteller. Andererseits
benötigt man einen konkreten Compiler, um mit C++ arbeiten zu können. Insofern
ist für die Praxis nicht unbedingt das reine C++ des Sprachstandards von Interesse,
sondern eher der Implementierungsumfang des gegebenen Compilers.
Kein heute
bekannter Compiler implementiert den Standard vollständig und zu 100 Prozent
korrekt. Dies bedeutet, dass es theoretisch möglich ist, ein korrektes Programm
zu schreiben, dass von keinem heutigen Compiler übersetzt werden kann. Dazu
muss man allerdings exotische Sprachmittel in ungewöhnlichen Kombinationen
verwenden. Nahezu alle bekannten Differenzen liegen im Bereich der Schablonen,
die zugegebenermaßen das von der Theorie her wohl schwierigste Sprachmittel
überhaupt darstellen. Nicht umsonst verzichten vergleichbare andere Sprachen
(Java) vollständig darauf.
Für die Praxis ist
die Standardkonformität der gängigen Compiler gut genug, um professionell damit
arbeiten zu können. Außerdem bringen die Compilerhersteller regelmäßig neue
Versionen ihrer Produkte auf den Markt. Gerade im Bereich der
Standardkonformität der Compiler wird sich in den nächsten zwei bis fünf
Jahren noch einiges ändern. Wir erwarten, dass die wichtigsten Compiler den
Standard immer besser unterstützen werden. Alle anderen werden mit Marketingproblemen
zu kämpfen haben und letztendlich vom Markt verschwinden. Evtl. auftretende
Probleme der Standardkonformität sind daher hoffentlich temporärer Natur.
Wir beschreiben in
diesem Buch deshalb Standard-C++ und
nicht den Implementierungsumfang eines bestimmten Produktes. Die in diesem Buch
vorgestellten Codebeispiele sind mit allen gängigen Compilern übersetzbar. An
den (wenigen) wichtigen Stellen, an denen es Probleme gibt, weisen wir explizit
darauf hin.
&& Sprachversionen
Die Sprache C++ ist ursprünglich
nicht in ihrer heutigen, standardisierten Form definiert worden. Es gab
vielmehr einige Vorversionen, die sich grob in die folgenden Entwicklungsstände
aufteilen lassen:
q C mit Klassen. Dies war die allererste Sprachversion, die
von Bjarne Stroustrup vor 1980 entwickelt wurde. Ziel war es, einige der
Probleme der Programmiersprache C zu überwinden, aber trotzdem deren Vorteile
wie z.B. Effizienz und Portabilität beizubehalten. „C mit Klassen“ wurde
damals in mehreren größeren Forschungsprojekten bei AT&T äußerst erfolgreich eingesetzt. Die
Sprache war damals nicht formal beschrieben, sondern wurde in Diskussionen
zwischen Mitarbeitern und Programmierern ständig verändert.
q ARM-Stand. Ca. 1983 trat „C mit Klassen“ erstmals aus
dem Forschungsbereich in die Öffentlichkeit. Durch den großen Erfolg war den
Beteiligten klar, dass nun eine Formalisierung notwendig war. Margaret Ellis
und Bjarne Stroustrup schrieben daraufhin (Mai 1990) als erstes formales Dokument The Annotated C++ Reference Manual (ARM), in dem die Sprache auf
dem damaligen Stand mehr oder weniger formal beschrieben wurde. Der Name „C++“
löste „C mit Klassen“ ab, dabei sollte das „C“ für die Aufwärtskompatibilität
zur Sprache C stehen, das „++“ dagegen für die Verbesserungen, die gegenüber C
nun zur Verfügung standen. Das ARM sollte auch zur Vorbereitung der Standardisierung
der Sprache durch das American National
Standardisation Institute (ANSI)
und später die International
Standardisation Organisation (ISO) dienen.
Das Annotated
Reference Manual war lange Zeit die Bibel aller C++-Programmierer, auch
heute noch verbindet mancher Softwareentwickler mit dem Wort „C++“ diese
Version. Sie beschreibt einen Sprachstand, der heute als ARM-Stand bezeichnet wird. In diesem Stand sind – neben dem
obligatorischen Klassenkonzept – bereits Ableitungen und virtuelle Funktionen,
Überladen von Operatoren, Referenzen, und eine rudimentäre typisierte
E/A-Bibliothek vorhanden. Im ARM werden bereits Schablonen (templates) und ein neues Konzept zur
Behandlung von Fehlersituationen (über sog. Ausnahmen
(exceptions)) vorgestellt, der
Status dieser Sprachmittel war jedoch „experimentell“. Man wollte damit Erfahrung
gewinnen, wie sich diese Innovationen in der Praxis bewährten – und in der Tat
hat sich die formale Definition dieser Sprachmittel (vor allem der Schablonen)
bis zum heutigen Standard noch einige Male verändert. Die in der Praxis
erarbeiteten Erfahrungen waren für die endgültige Definition dieser Sprachmittel
eine große Hilfe.
q Vor-Standardisierungs-Stand (pre-standard).
Im Dezember 1989 wurde das X3J16-Komittee der ANSI formal mit der Standardisierung
der Sprache beauftragt, 1991 kam die Arbeitsgruppe 21 der ISO (ISO WG21) hinzu.
Als Basis für die Standardisierung diente das ARM sowie der Standard der
Programmiersprache C (ISO/IEC 9899), neben weiteren Dokumenten wie z.B.
Konventionen über die Terminologie oder den für Quellcodes zu verwendende
Zeichensatz.
Im Zuge der Arbeit des
Standardisierungskomitees wurde die Sprache nach und nach verändert und
erweitert. Die im ARM noch als „experimentell“ gekennzeichneten Sprachmittel
wurden prinzipiell akzeptiert und weiter entwickelt, weitere wesentliche Teile
(wie z.B. Namensbereiche (name spaces))
kamen hinzu. Parallel zur Standardisierung der Sprache an sich wurde die
Definition einer Laufzeitbibliothek in Angriff genommen.
q Standard. Am 1. September 1998 präsentierte das Komitee
das Ergebnis der Standardisierungsbemühungen: Der International Standard ISO/IEC 14882 liegt nun in der ersten
Ausgabe (First Edition 1998-09-01)
vor. Damit sind Syntax und Semantik der Programmiersprache C++ sowie der
zugehörigen C++ Standardbibliothek international festgeschrieben.
&& Pre-Standard
und Standard
Für die
Softwareentwicklung heute sind diese beiden „Versionen“ der Sprache relevant.
Neue Programme sollten selbstverständlich in Standard-C++ erstellt werden,
soweit der verwendete Compiler dies zulässt – die Unterschiede sind (wie
gesagt) in der Praxis verschmerzbar.
Eine sehr große
Anzahl bestehender C++-Programme ist jedoch nicht nach den Vorgaben im Standard
erstellt worden, da der Standard bei ihrer Erstellung noch gar nicht
existierte. Glücklicherweise können diese Programme in der Regel auch mit einem
standardkonformen Compiler übersetzt werden, wenn man einige Besonderheiten beachtet.
Eventuell sind einige kleinere Korrekturen notwendig, die jedoch auf Grund von
Syntaxfehlermeldungen bei der Übersetzung sofort erkannt werden können.
Auf Grund der
zahlreichen bestehenden C++-Altsysteme ist der Pre-Standard für die Praxis also
nicht ganz unwichtig. Wir gehen deshalb wo erforderlich gesondert darauf
ein.
&& Voraussetzungen
Dieses Buch ist
kein Einführungsbuch in die Programmierung. Wir gehen davon aus, dass der Leser
bereits Erfahrung in der Programmierung von Anwendungen hat, die über
triviale Beispiele hinausgehen.
Wir behandeln
weiterhin keine Fragen der Installation oder der Bedienung von Compilern,
Entwicklungsumgebungen, Debuggern etc. Wir gehen davon aus, dass der Leser
einen funktionsfähigen Compiler besitzt und auch bedienen kann. Auf der Internetseite
des Buches gibt es Hinweise zu gängigen Entwicklungssystemen, darunter auch zu
nichtkommerziellen Produkten wie dem GNU-Compiler. Weiterhin gibt es auf der
Internetseite Standard-Projektdateien bzw. Makefiles für die gängigen Systeme.
&& Support
über das Internet
Das Buch wird über
eine Internetrepräsentanz unterstützt. Die Einstiegsseite ist
http://www.PrimaProgramm.de
Der Quellcode
sämtlicher größerer Beispiele ist über diese Seite erreichbar. Die Quellen
sind nach Kapiteln geordnet, für die vollständigen Fallbeispiele und die
einzelnen Versionen des durchgängigen Projekts gibt es zusätzlich fertige
Projektdateien für die wichtigsten Compiler, sowie eine generelle Make-Datei.
Darüber hinaus
enthält die Seite ständig Informationen über neuere Entwicklungen aus dem
Bereich C++ sowie eine Reihe interessanter Links zu anderen Ressourcen über
C++, Objektorientierung und verwandte Themen. Es lohnt sich also, öfters mal
vorbeizuschauen. Eine weitere Quelle von Informationen bietet der Server des
Vieweg-Verlages, der unter der Adresse
http://www.Vieweg.de
erreichbar ist.
Wer wirklich
keinen Internetzugang hat, kann die Quelltexte auch auf Diskette zu einem
Kostenbeitrag von EUR 10.- erhalten. Bitte wenden Sie sich dazu an den Verlag,
oder direkt an den Autor.
Anregungen,
Wünsche und Verbesserungen sind willkommen an folgende Email-Adresse:
Martin.Aupperle@PrimaProgramm.de
&& Literatur
Die folgende Liste enthält eine
Aufzählung der aus Sicht des Autors wichtigsten Bücher und Veröffentlichungen:
q C++ Standard
Der C++ Standard ist das
Referenzdokument für die Sprache C++. Er kann vom ANSI oder der ISO gegen einen
Kostenbeitrag von US$18 in elektronischer Form bezogen werden (Adresse siehe Internetseite
des Buches) .
Die Sprache wird, wie es sich für einen
Standard gehört, präzise und vollständig beschrieben. Teilweise werden kleine
Beispiele gegeben. Das Papier ist äußerst zäh zu lesen und es bedarf ausreichender
Erfahrung mit C++, um überhaupt sinnvoll damit arbeiten zu können. Auf jeden
Fall nichts für C++-Neulinge oder für die Softwareentwicklung in der Praxis,
aber die definitive Entscheidungsinstanz, wenn es um Streitfragen der Syntax
oder Semantik geht.
q The Draft C++ Standard
Dieses Papier beschreibt den Stand der
Sprache, wie er zur Normung durch ANSI/ISO angenommen wurde. Der Draft (wie das Papier vereinfacht genannt
wird) enthält nur marginale Unterschiede zum Standard, ist aber dafür im
Internet (Adresse siehe Internetseite des Buches) frei erhältlich.
q Bjarne Stroustrup: The C++ Programming
Language, 3rd ed. Addison-Wesley. Reading, Massachusetts, 1997
Das Buch gibt eine vollständige
Übersicht über die Sprache C++. Es behandelt den vollständigen Sprachstandard
nach ANSI/ISO ohne Berücksichtigung von Defiziten heutiger Compiler etc. Zu den
Sprachkonstruktionen werden kurze Beispiele gegeben, die die Konstrukte
erläutern. Jedes Kapitel schließt mit Aufgaben und Übungen für den Leser,
allerdings werden keine Antworten gegeben. Das Buch enthält am Ende auch ein
Kapitel über Designfragen und ihre Auswirkungen auf die Gestaltung von Programmiersprachen
allgemein und C++ im Besonderen. In Fachkreisen wird das Buch auch einfach als The Book oder The Bible bezeichnet.
q Bjarne Stroustrup: The Design and Evolution
of C++. Addison-Wesley. Reading, Massachusetts, 1994
Das Buch ist sehr interessant für Leute,
die sich für Historie und Hintergrund der Sprache C++ interessieren. Der Autor
gibt Begründungen, warum bestimmte Spracheigenschaften so und nicht anders
implementiert wurden. Insbesondere das Verhältnis zur Sprache C und die daraus
resultierenden Konsequenzen werden ausführlich behandelt. Mögliche Alternativen
oder mögliche zusätzliche Sprachelemente werden ebenfalls angesprochen und
auch die Gründe, warum sie letztendlich verworfen wurden.
q Nicolai M Josuttis: The C++ Standard
Library. Addison-Wesley. Reading, Massachusetts, 1999
Dieses Buch befasst sich ausschließlich mit
der C++ Standardbibliothek. Die Bibliothek wird vollständig und ausführlich
behandelt. Zu allen Bereichen gibt es Beispiele.
q Marshall Cline and Greg Lomow: C++ FAQs. Addison-Wesley.
Reading, Massachusetts, 1995
FAQ bedeutet Frequently Asked Question (etwa: häufig gestellte Frage). Das Buch
behandelt solche häufig gestellten Fragen zu C++. Die Antworten sind kurz und
präzise und werden teilweise durch Erläuterungen oder Kommentare ergänzt. Im
Internet ist eine zweite, kleinere Version der FAQs vorhanden, die regelmäßig
in den Newsgroups gepostet wird und auch über die Internetseite des Buches
erreichbar ist. Marshal Cline pflegt auch die elektronische Version. Die
elektronische Version ist aktueller, das Buch ist dagegen wesentlich ausführlicher.
q Martin Aupperle: Die Fortgeschrittene Kunst
der Programmierung mit C++. Vieweg-Verlag, 2003
In diesem Buch geht es um Fragen der
industriellen Softwareentwicklung mit C++. Der erste Teil befaßt sich mit der
C++-Standardbibliothek, und zwar sowohl mit dem Einsatz der bestehenden
Funktionalität als auch mit ihrer Erweiterung durch eigene Konstruktionen. Im
zweiten Teil werden Programmiertechniken vorgestellt, die sich in großen
Projekten bewährt haben. Zu den Themen des zweiten Teils gehören Entwurfsmuster,
Techniken zur Beherrschung von Komplexität, Kontraktorientiertes
Programmieren, Zusammenarbeit mit anderen Programmiersprachen, Techniken zum
Fehlermanagement sowie Fragen der Softwarequalität. Zum Buch gibt es eine Internetseite, von der auch ein
Stilhandbuch (styleguide) heruntergeladen
werden kann.
q C++ Report
Eine monatlich erscheinende
Fachzeitschrift ausschließlich zum Thema C++. Bekannte Autoren schrieben sowohl
für Profis, Fortgeschrittene und auch für C++-Einsteiger. Die Zeitschrift ist
allerdings seit Sommer 2000 eingestellt. Es lohnt sich auf jeden Fall, in
einer Bibliothek einmal die letzten Jahrgänge durchzublättern.
q C/C++ Users Journal
Eine monatlich erscheinende Fachzeitschrift,
die sich mit Themen rund um die Programmiersprachen C und C++ befasst. Die Zeitschrift enthält
regelmäßig Beiträge bekannter Autoren zum Thema C++. Nach der Einstellung des
C++ Report schreiben die meisten Autoren nun für „CUJ“, wie das C/C++ Users Journal
vereinfacht genannt wird.
Darüber hinaus
gibt es eine Reihe interessanter Quellen im Internet. Die Internetseite des
Buches enthält einige Links.
&& Einige
Anmerkungen
Zum Schluss dieses
einführenden Kapitels betrachten wir noch einige Behauptungen über C++, die man
in Programmiererkreisen oft hören kann, die aber so pauschal nicht richtig
sind.
& C++ ist nichts anderes als C mit einigen Verbesserungen
Diese Aussage ist
richtig und zugleich falsch – je nach Blickwinkel.
Richtig ist, dass
C++ syntaktisch (mit unwesentlichen Ausnahmen) eine Obermenge der Sprache C
ist. Das bedeutet z.B., dass ein „ordentliches“ C Programm auch mit einem C++
Compiler übersetzt werden kann. Durch die neuen Sprachmittel werden die
bekannten Probleme der Programmierung mit C verringert oder ganz vermieden.
Dies ist jedoch
nur die halbe Wahrheit. Richtig ist nämlich auch, dass C++ eine völlig andere
Programmiersprache als C ist, wenn man die Programmiertechniken betrachtet. C++
bietet ganz andere Möglichkeiten, Programme wartungsfreundlicher, besser
wiederverwendbar und nicht zuletzt schneller und damit kosteneffizienter zu
erstellen als dies mit den traditionellen Programmierstilen möglich war. Aus dieser Sicht ist die obige Aussage
völlig falsch.
& Java/C/Basic/Smalltalk/Perl/Delphi/Lisp
ist besser als C++!
Die Liste der
„besseren“ Programmiersprachen könnte noch beliebig erweitert werden. Aber was
bedeutet „besser“? Sicherlich gibt es Problemstellungen, für die C++ nicht die
geeignete Sprache ist. Möchte man z.B. Programme erstellen, die innerhalb der
grafischen Umgebung eines Web-Browsers ablaufen sollen, ist vielleicht Java
oder sogar eine Scriptsprache besser geeignet.
Alle diese
Sprachen haben ihren Anwendungsbereich. Betrachtet man jedoch die große Gruppe
der allgemeinen Problemstellungen (die also nicht auf spezielle Randbedingungen
Rücksicht nehmen müssen), ist C++ in den allermeisten Fällen die bessere Wahl.
In der Praxis
kommen jedoch auch nicht-technische Aspekte hinzu. Die Komplexität der Sprache
schreckt Programmierer und Manager gleichermaßen ab. Java wird oft deshalb als
geeigneter angesehen, weil die Syntax und das „Handling“ einfacher sind. Dies
ist korrekt – die Komplexität steckt jedoch in den Anforderungen, die einmal mit einem Programm realisiert werden
sollen. Es ist durchaus nicht klar, wieso eine einfachere Sprache besser zum
Lösen schwieriger Aufgaben geeignet sein soll als eine mächtigere Sprache.
Folgt man solchen Argumentationen, müsste man eigentlich in Assembler oder Basic
am allerbesten programmieren können. Die Erfahrung zeigt, dass dies jedoch nicht so ist. Vergessen darf man allerdings
auch nicht, das mächtige Werkzeuge auch ausreichend Kompetenz im Umgang erfordern
– sonst sind die Ergebnisse verheerend.
& Aber C++ ist so
komplex!
Dieses Argument
wird oft von Verfechtern von einfacheren Programmiersprachen wie C oder Java
vorgebracht. Es ist auf der einen Seite sogar berechtigt! C++ kann eine extrem
komplexe Sprache sein – man kann Sprachkonstrukte so kombinieren, dass wirklich
schwierige und teilweise fehlerträchtige Programme entstehen.
Andererseits ist
es so, dass normale
Aufgabenstellungen in C++ einfach, sicher, lesbar und damit wartungsfreundlich
implementiert werden können. Ein Einsteiger kann mit C++ schnell Ergebnisse,
und zwar vor allem deshalb, weil er sich auf die problemorientierten Aspekte
konzentrieren kann und sich nicht so sehr um die maschinenorientierten Dinge
kümmern muss. Die mächtigen Abstraktionsmittel der Sprache C++ sowie die
hervorragende Unterstützung durch die Standardbibliothek machen dies möglich.
Die meisten der
schwierigeren Konstruktionen werden heute nicht von Anwendungsprogrammierern,
sondern von Bibliotheksimplementierern verwendet. Sie können durch Einsatz
dieser Sprachmittel hervorragende Performance, geringen Ressourcenverbrauch
sowie andere positive Eigenschaften ihrer Bibliotheken realisieren. Der Anwender sieht meist von
dieser Komplexität nichts, da sie in der Implementierung der Bibliotheken verborgen
ist.
Dies bedeutet
natürlich nicht, dass man zur Implementierung von Bibliotheken die Sprache
derart ausreizen muss. Häufig verwendete Bibliotheken wie z.B. die C++
Standardbibliothek können jedoch davon
Gebrauch machen, um das Letzte an Performance herauszuholen.
Ein bekannter
Ansatz geht davon aus, dass mächtige Werkzeuge notwendigerweise auch
entsprechend komplex sind. Dies trifft auch für C++ zu, allerdings mit der
Ergänzung, dass ein Programmierer mit dieser Komplexität nicht unbedingt
konfrontiert werden muss: Er kann sich auch auf die einfacheren Sprachmittel
beschränken.
& Aber C++ ist
langsam!
So oft man dieses
Argument auch hört: Es ist schlichtweg falsch. Übersetzt man ein Programm mit
einem C- und einem C++-Compiler, werden beide Versionen gleich schnell laufen.
C++ erzeugt daher nicht automatisch ineffizienteren Code.
Ein anderer
Vergleich ist hier schon aussagekräftiger: Implementiert man eine gegebene
(nicht triviale) Problemstellung einmal mit C und dann getrennt mit C++, werden
sich beide Implementierungen auf Grund der unterschiedlichen zur Verfügung
stehenden Sprachmittel der beiden Sprachen wahrscheinlich stark unterscheiden.
Folgende Effekte können häufig beobachtet werden:
q
Der Programmierer hat auch in C++ wie in C
programmiert, d.h. die Lösungen unterscheiden sich nur unwesentlich. Die
Laufzeiten sind vergleichbar.
q
Der Programmierer verwendet zwar die C++
Sprachmittel, jedoch nicht unbedingt korrekt. Durch die ungeschickte
Programmierung läuft die C++ Implementierung deutlich langsamer und ist evtl.
auch deutlich größer.
q
Der Programmierer verwendet die C++
Sprachmittel und setzt diese sorgfältig und korrekt ein. Das C++ Programm läuft
schneller als die C-Version!
Wie man sieht,
hängt alles von der korrekten Verwendung der Sprache ab. Es ist durchaus
möglich, dass C++ Programme sogar effizienter als ihre C-Pendants sind, wenn
man Design und Implementierung in Richtung Laufzeit optimiert. Dies macht C++
z.B. auch für die Implementierung von Betriebssystemen oder embedded systems geeignet.
In größeren
Systemen tritt allerdings noch ein weiterer Effekt auf. Implementierungen in
C++ neigen dazu, qualitativ hochwertiger als Implementierungen in niedrigeren
Sprachen zu sein. Wiederverwendbarkeit und Wartungsfreundlichkeit sowie ein
besserer Umgang mit Fehlersituationen sind in C++ nicht nur leichter zu
realisieren als in C, sondern kommen oft nahezu automatisch, wenn man einige
Entwicklungsprinzipien beachtet. Dadurch tendieren C++ Programme auch bei
gleicher Funktionalität dazu, mehr Ressourcen als C-Programme zu benötigen.
& Aber C++ ist
nicht plattformunabhängig!
Dieses Argument
wird meist im Vergleich zu Java zitiert. Bei genauerer Betrachtung ist aber
auch dieses Argument nicht haltbar. C++ - Programme sind sogar noch eher
plattformunabhängig als Java-Programme. Dies liegt natürlich an den
unterschiedlichen Sprachversionen sowie an den unterschiedlichen Versionen der
Java Virtual Machine, die auf den
verschiedenen Rechnern vorhanden sein können. In der Praxis bedeutet dies, dass
aus Java’s Anspruch Write Once, Run
Anywhere bereits Write Once, Test
Anywhere geworden ist. Dies bedeutet einen erheblichen Aufwand für die
industrielle Softwareentwicklung. Standard-C++ - Programme verhalten sich
dagegen auf jeder Plattform absolut gleich.
Allerdings fehlen
C++ standardmäßig Bibliotheken zum Zugriff auf die zu Grunde liegende Plattform
oder für grafische Benutzeroberflächen, so wie sie bei Java z.B. mit dem Abstract Windowing Toolkit oder mit Swing vorhanden sind. Da heute die
meisten Programme eine GUI benötigen, scheint C++ hier zunächst im Nachteil zu
sein. Es gibt allerdings externe C++ - Bibliotheken, die eine plattformunabhängige
GUI-Programmierung ermöglichen. Somit ist hier C++ nicht im
Nachteil: der Unterschied zu Java ist lediglich, dass die GUI-Bibliotheken
bereits „zum System“ gehören, während sie bei C++ extern hinzugenommen werden
müssen. Hier kommt ein weiterer Vorteil zum tragen: während man z.B. in Java in
der Praxis die Swing-Bibliothek verwenden muss, kann man bei C++ eine Auswahl aus
mehreren Anbietern treffen.