HEIC-Konverter kostenlos

OpenOffice ist eine kostenlos zum Download erhältliche Programmgruppe, welche unter anderem ein Textverarbeitungsprogramm enthält, das mit den Datei-Endungen *.doc und *.docx super klarkommt, sprich womit man diese Dateien nicht nur öffnen, sondern auch weiterverarbeiten kann.

Der Prototyp Bevor Sie eine Funktion verwenden können, müssen Sie dem Compiler zunächst mitteilen, dass es eine Funktion dieses Namens gibt, wie viele und welche Parameter sie hat und welchen Typ sie zurückliefert.

HEIC in JPEG Online konvertieren

Der HEIC-Konverter ist ein kostenloses Online-Tool für Windows und Mac, das Fotos von HEIC in JPG konvertieren kann.

Implizite Typumwandlung Meistens kann man Variablen und Konstanten verschiedener Datentypen einander zuweisen. Als Programmierer sollten Sie aber ein wenig die dabei angewandten Prinzipien kennen, um beurteilen zu können, ob die automatische Umwandlung auch die ist, die Sie wollen. Vorsicht ist beim umgekehrten Fall geboten. Hierbei können Informationen verloren gehen und sogar völlig andere Ergebnisse herauskommen, als Sie vielleicht erwarten.

Wenn noch Konstanten im Quelltext stehen, kann man von Hand nachrechnen und aufmerksam werden. Wenn aber andere Variablen beteiligt sind, wird das schon schwieriger, zum Beispiel: Bei der gegenseitigen Zuweisung von ganzen und Dezimalzahlen sind nicht so viele Fallstricke ausgelegt. Sie sollten lediglich daran denken, dass der gesamte Teil nach dem Komma abgetrennt wird, wenn Sie als Ergebnis eine Ganzzahl angeben. Jede Variable muss über einen eindeutigen Typ verfügen, und bei Zuweisungen und Vergleichen müssen die Variablen beziehungsweise Konstanten als kompatibel bekannt sein, sonst wird eine Fehlermeldung ausgegeben.

Überhaupt weist Sie der Compiler mit Hilfe von Warnungen oft auf mögliche Fehler oder Mehrdeutigkeiten hin, etwa wenn er annimmt, dass Sie eine Anweisung anders gemeint haben, als sie nun im Quelltext steht.

Lesen Sie diese Meldungen aufmerksam und versuchen Sie stets die Ursachen dafür zu verstehen. Auf diese Weise werden Sie auch viel über die richtige Programmierung lernen. Explizite Typumwandlung Anstatt sich auf die automatische Typkonvertierung zu verlassen, kann es auch manchmal sinnvoll sein, dem Compiler eine Regel zur Umwandlung vorzuschreiben.

Für die explizite Typumwandlung verwenden die C-Programmierer einen sehr bildlichen Ausdruck, nämlich cast , das englische Wort für Gipsverband. Die andere Möglichkeit ist, die Variable in Klammern zu setzen und den Typ davor: Da Sie aber erst noch einige weitere Begriffe kennen müssen, um diese zu verstehen, verschieben wir die Diskussion auf später Seite.

Aufzählungstypen Nicht immer sind numerische Werte für eine Variable sinnvoll. Manchmal will man für sie nur einen begrenzten Wertebereich zulassen. Hier sollten Sie einen Aufzählungstyp verwenden. Sie deklarieren ihn mit dem Schlüsselwort enum , einem Typnamen und einer Liste von Werten, eingeschlossen in geschweiften Klammern und getrennt durch Kommas.

Für unseren Status können wir schreiben: Operatoren Variablen alleine nützen noch nicht viel. Man muss sie auch miteinander verknüpfen, sie zuweisen, verändern und ausgeben können.

Dazu dienen die Operatoren. Einige erinnern noch daran, dass C einmal als besonders hardwarenahe Sprache entworfen wurde. Überblick Auf jeden einzeln einzugehen, würde an dieser Stelle zu weit führen. Ich will Ihnen daher in Tabelle Tab: Operatoren eine Liste mit den wichtigsten Operatoren geben.

Wenn Ihnen Verschiedene nicht gleich klar sind, müssen Sie sich deshalb keine Sorgen machen: Tatsächlich gibt es ein paar Operatoren, deren Bedeutung vom Kontext abhängt, in dem sie verwendet werden. Für den Augenblick ist es hilfreich, wenn Sie die Quelltexte sehr konzentriert durchsehen und sich bei jeder Anweisung nach deren Bedeutung fragen.

Dort regelt beispielsweise der Grundsatz Punkt vor Strich, dass zunächst multipliziert und dann erst addiert wird. Auch innerhalb jeder Gruppe kann es noch Reihenfolgen geben. Sie können nämlich sowohl vor als auch hinter der Variablen stehen, auf die sie wirken.

Man nennt diese beiden Stellungen auch Präfix und Postfix. Die Operatoren werden meist nicht als einziger Bestandteil einer Anweisung verwendet, sondern in kompliziertere Ausdrücke eingebaut. Steht der Operator vor der Variable, wird er zuerst ausgeführt und dann erst der Ausdruck ausgewertet.

Steht er dagegen dahinter , wird erst der gesamte Ausdruck ausgewertet und dann der Operator angewandt. Anfänger empfinden diese Schreibweise stets als verwirrend; die erfahrenen Programmierer sehen sie dagegen als besonders elegant und kompakt an. Überlegen oder probieren Sie mal selbst, welche Ausgabe der folgende Code erzeugt: Der Bedingungsoperator Einer der Operatoren, die in Tabelle fehlen, ist?: Er hat folgende allgemeine Form: Ausdruck2 Die Verwendung ist ganz einfach: Ist die Bedingung wahr, wird Ausdruck1 ausgewertet, ist sie falsch, dann Ausdruck2.

Ausdrücke Gerade war schon von Ausdrücken die Rede. Was ist eigentlich ein Ausdruck? Dem Begriff des Ausdrucks engl. Dieser hängt von den beteiligten Variablen und Operatoren ab. Betrachten wir beispielsweise folgende Variablen: Zusammenfassung Aus diesem Abschnitt sollten Sie sich Folgendes merken: Kommentare können auf zwei Arten in den Programmtext eingefügt werden: Jedes Programm sollte mindestens so viele Kommentar- wie Anweisungszeilen enthalten.

Eine automatische Initialisierung erfolgt nicht. Als Typen für Ganzzahlen gibt es je nach Wertebereich short , int und long. Die Typen char , short , int und long können den Zusatz unsigned erhalten. Der Datentyp void steht für einen nicht existenten Wert. Wenn die Datentypen innerhalb eines Ausdrucks nicht kompatibel zueinander sind, versucht der Compiler, die Variablen selbstständig in einen anderen Typ umzuwandeln.

Um auf diesen Vorgang Einfluss zu nehmen, können Sie auch explizit Typkonvertierungen vorschreiben. Der Typ des Werts eines arithmetischen Ausdrucks wird bestimmt von dem höchstwertigen Teilausdruck. Daten und Objekte werden mit Hilfe von Operatoren verknüpft, verändert und ausgelesen. Übungsaufgaben Was passiert, wenn man einer Variablen vom Typ int eine Zahl mit Dezimalstellen zuweist?

Welchen Wert hat eine Variable, nachdem sie deklariert wurde? Erklären Sie den Unterschied zwischen expliziter und impliziter Typkonvertierung. Die Funktion sizeof hat den Zweck, den Speicherverbrauch eines Datentyps oder einer Variablen zu bestimmen. Welche Ausgabe liefert folgendes Programm? Für eine Variable x soll ausgegeben werden, ob sie 0 ist oder nicht. Was ist hier falsch? Dabei spielt natürlich auch eine Rolle, dass es sich dabei um freie Software handelt, der Compiler also kostenlos erhältlich ist.

Installation Sie können sich stets mit der neuesten Version des Compilers aus dem Internet versorgen, am besten von gcc. Allerdings werden Sie dazu kaum je Anlass verspüren.

In jeder Linux-Distribution ist nämlich dieser Compiler enthalten -- schon allein deshalb, weil er zum Kompilieren des Linux-Kernels gebraucht wird. Erscheint eine neue Version, bringen die Hersteller der Distributionen sie meist relativ schnell in die Form von Installationspaketen, die Sie dann nur noch von den Sites der Hersteller herunterladen müssen.

Die eigentliche Installation auf Ihrem Rechner ist dann mit den jeweiligen grafischen Werkzeugen oder mit rpm leicht zu erledigen. Wenn Ihr Programm aus mehreren Quelltextdateien besteht, können Sie auch mehrere hintereinander angeben.

Dabei dürfen die Dateien auch in mehreren Verzeichnissen liegen, müssen Sie dazu nur jeweils den vollständigen Pfad angeben, zum Beispiel: Die wichtigsten sind in Tabelle zusammengefasst; ich werde sie Ihnen im Folgenden kurz erläutern. Die Reihenfolge, in der Sie die Optionen angeben, ist völlig egal. Sie müssen lediglich sicherstellen, dass jeweils eine Option und ihr zugehöriger Parameter zusammen stehen.

Name für die ausführbare Datei Vermutlich sind Sie mit dem Namen a. Debug-Informationen Jeder Programmierer macht Fehler. Um diese aufzudecken, gibt es Debugger vom englischen Wort bug, das eigentlich Käfer, umgangssprachlich auch Programmierfehler bedeutet; ob man in den ersten riesigen Elektronenhirnen mal tatsächlich Käfer fand, ist nicht zweifelsfrei überliefert.

Debugger sind Hilfsprogramme, mit denen Sie das Programm quasi beim Ablauf beobachten können, also an bestimmten Stellen stoppen, Werte von Variablen ausgeben oder um einzelne Schritte weiterlaufen lassen können. Damit der Debugger die Anweisungen im ausführbaren Programm den Quelltextzeilen zuordnen kann, braucht er entsprechende Informationen. Diese werden durch die Option -g in das Programm eingefügt. Fehler und Warnungen Bei Syntaxfehlern also Verletzung der Sprachregeln stoppt der Compiler meist sofort und gibt die Datei sowie die Nummer der Codezeile aus, in der er den Fehler festgestellt hat.

Wenn Sie wie in folgendem Beispiel ein Semikolon vergessen: Manchmal wird ein Syntaxfehler aber gar nicht als solcher erkannt, da die Anweisung in einem anderen Kontext durchaus korrekt sein könnte. Eine solche Fehlerinterpretation verwirrt den Compiler dann bei der Übersetzung der nachfolgenden Anwendungen so sehr, dass es meist Fehlermeldungen hagelt.

Wenn Sie an der ersten Stelle, an der ein Problem auftrat, nichts finden können, sollten Sie daher auch die Zeilen darüber betrachten, ob sich in diesen nicht die Ursache finden lässt. Anders verhält es sich mit Warnungen. Diese sind nicht so schwer wiegend, dass dadurch der Übersetzungsvorgang gleich eingestellt werden müsste. Andererseits handelt es sich dabei um potenzielle Probleme, die im einfachsten Fall ignoriert werden, im schwersten Fall aber zur Laufzeit einige unerwünschte Effekte hervorrufen können.

So weist Sie der Compiler darauf hin, dass Sie etwas unschön geschrieben haben oder mehr als nötig, dass er etwas anders auffasst, als Sie es vermutlich gemeint haben, und so weiter. Für fast jede Warnung gibt es eine eigene Option, jeweils von der Form -W warnungs-typ. Zum Glück gibt es aber auch Schalter, die ganze Gruppen von Warnungen aktivieren. Eine ist dabei besonders wichtig: Mit -Wall schalten Sie alle Warnungen ein, die auf unschönen Code hindeuten. Dabei handelt es sich beispielsweise um nicht oder unzureichend initialisierte Variablen, Typverwechslungen, missverständliche Klammerungen oder unbenutzte Variablen.

Sie sollten die Warnungen ernst nehmen und solchen Code vermeiden. Wenn wir etwa schreiben: Sie sehen daran auch, dass Sie der Compiler bei einem Durchlauf nicht auf alles gleichzeitig hinweist.

Hier ist beispielsweise die Variable p genauso unbenutzt wie s , wird jedoch nicht angemahnt. Erst wenn Sie s entfernen würden, käme die Warnung für p. Die Schreibweise -Wall steht zwar für warnings, all, ist aber nicht zufällig auch als wall, also Wand, zu lesen. Sie können sich dabei eine Schutzmauer um Ihren Code vorstellen; wenn er sie überwindet, ist er schon mal in ganz guter Verfassung. Daher empfehle ich Ihnen, diesen Schalter immer zu verwenden. Kompilierung zur Objektdatei Wenn Sie Programme schreiben, die aus mehreren Dateien bestehen, so geben Sie diese üblicherweise nicht alle auf einmal beim Aufruf des Compilers an.

Wenn Sie nämlich in einer davon einen Fehler gefunden haben, diesen korrigieren und die Übersetzung neu starten, werden auch alle davor stehenden nochmals kompiliert. Bei Programmen mit mehr als einer Quelldatei darf man die einzelnen Quellen nur bis zum Objektcode übersetzen -- und das jeweils mit einem eigenen Compileraufruf für jede Datei. Sind alle Files übersetzt, können sie mit einem weiteren Aufruf zusammengelinkt werden. Um den Compiler anzuweisen, beim Objektcode aufzuhören und das Linken zu einem ausführbaren Programm gar nicht erst zu versuchen, verwenden Sie die Option -c.

Besteht der Quelltext Ihres Programms beispielsweise aus den Dateien datei1. Diese hatte ich Ihnen auf Seite schon mal vorgestellt. Steht der Dateiname in normalen Anführungzeichen, so wird nach der Header-Datei zusätzlich im aktuellen Verzeichnis gesucht.

Gelegentlich werden Sie für die Übersetzung aber auch Header-Dateien benötigen, die weder in den Systemverzeichnissen noch im aktuellen Verzeichnis stehen. Dann können Sie zusätzlich Verzeichnisse angeben, in denen der Compiler nach Headern suchen soll. Dabei können Sie relative Pfade etwa -I.. Der Linker, der die einzelnen Objektdateien zu einem ausführbaren Programm zusammenfügen soll, verbindet die Aufrufe mit den eigentlichen Funktionen auf Ebene der Maschinensprache.

Damit er die Bibliotheksfunktion dabei findet, müssen Sie beim Linken noch die entsprechende Bibliothek dazubinden. Dazu haben Sie zwei Möglichkeiten: Diese arbeitet ganz analog zu der für Include-Dateien. Die Option -L wirkt dabei indes nur auf die -l -Befehle, die Sie danach angeben. Somit sollten Sie stets zunächst die Suchpfade und dann die Binde-Kommandos schreiben. Der Linker sucht sich dabei alle Symbole heraus, die im restlichen Programm zwar verwendet, aber nicht definiert werden.

Auch dabei ist die Reihenfolge entscheidend. Optimierung Normalerweise versucht der Compiler, die ihm gestellte Aufgabe, also das Übersetzen eines Programms, möglichst schnell zu erledigen. Das ist während des Entwicklungszyklus sicherlich auch für den Programmierer hilfreich. Ist das Programm dann aber einmal fertig und soll seine Arbeit verrichten, so sind Sie vermutlich daran interessiert, dass es diese so schnell wie möglich vollbringt.

Dafür schalten Sie die Optimierung ein. Compiler-Optimierung ist ein eigenes wissenschaftliches Fachgebiet. Der GCC war lange Zeit dafür bekannt, dass er besser optimiert als viele seiner kommerziellen Konkurrenten. Unter Linux liegt er immer noch in der Spitzengruppe. In älteren Programmierbüchern können Sie oft lesen, wie man Code schreiben sollte, damit er vom Compiler optimal umgesetzt werden kann. Aufgrund der Fähigkeiten des automatischen Optimierers können Sie sich diese Feinheiten heute sparen.

Natürlich sollten Sie immer noch Ihre Algorithmen möglichst ökonomisch organisieren -- aber die Beachtung von bestimmten Reihenfolgen von Anweisungen oder Befehle, um Variablen in die Prozessorregister unterzubringen, sind nicht mehr nötig. Sie müssen nicht einmal wissen, was der Optimierer eigentlich macht, denn Sie interessiert es ja nur, dass Ihr Programm möglichst schnell läuft.

Die Standardoption zum Einschalten der Optimierung ist -O. Es gibt dazu sogar noch Steigerungen: Mit -O2 und -O3 schalten Sie noch zusätzliche Optimierungsverfahren dazu. Zuweilen kann das aber des Guten zu viel werden, denn manche Programme zeigen bei zu hohem Optimierungsniveau ein unvorhersagbares Verhalten bis hin zu Abstürzen.

Daher ist das einfache -O meist die Methode der Wahl. Ein so optimiertes Programm läuft natürlich auf Rechnern mit Prozessoren der vorhergehenden Generationen nicht mehr. Dazu geben Sie einfach ein: Eine wesentliche Vereinfachung der Bedienung können Sie schon mit xinfo erreichen.

Dann erhalten Sie die Informationen wenigstens in einem X-Window und können etwas mit der Maus klicken. Dort müssen Sie nur nach dem Stichwort gcc suchen und dieses anklicken. Dann sollten Sie die in Abbildung dargestellte Seite vor sich sehen. Editieren mit NEdit Vielleicht hatten Sie während des Lesens ab und zu schon den Wunsch, auch ein kleines Programm zu schreiben und zu übersetzen.

Ich habe schon viel über Programmierung erzählt, aber noch nichts, wie man den Quelltext eigentlich eintippt. Entsprechend vielseitig ist die Palette der Bedienphilosophien. Viele Editoren sind meiner Erfahrung nach für Anfänger ungeeignet, da dabei sehr eigenwillige Tastenkombinationen nötig sind. Und da ich davon ausgehe, dass Sie vor Ihrer Beschäftigung mit Linux schon einige Erfahrungen mit Windows oder MacOS gemacht haben, möchte ich Sie lieber auf Werkzeuge hinweisen, deren Handhabung Ihnen etwas vertrauter vorkommen müsste.

Es macht doch keinen Sinn, wenn Sie sich nicht nur in eine neue Programmiersprache, sondern gleichzeitig auch in einen ungewohnten Texteditor einarbeiten müssten, oder? Später ab Seite will ich Ihnen noch einige Editoren im Detail vorstellen sowie verschiedene integrierte Entwicklungsumgebungen besprechen.

Damit nicht alles aus dem Zusammenhang gerissen wird, Sie aber jetzt schon Ihre ersten Programme schreiben können, möchte ich an dieser Stelle einen Editor herausgreifen und Ihnen ein paar Tipps zur Arbeit mit NEdit geben. Er lehnt sich insbesondere an die unter Windows und MacOS verwendeten Konventionen an und bietet zum Beispiel Menüs, Dialogfenster, Bearbeitungsmöglichkeiten mit der Maus sowie die gewohnten Shortcuts. Viele Distributionen beinhalten bereits NEdit.

Natürlich können Sie sich auch mit der neuesten Version aus dem Internet versorgen; dort gibt es sogar schon vorkompilierte Versionen. Sehen Sie dazu am besten auf der Homepage www. Die Bedienung erfolgt in gewohnter Weise. Ein sehr hilfreiches Feature ist das Syntax-Highlighting , das die verschiedenen Sprachelemente wie Schlüsselwörter, Präprozessordirektiven oder Kommentare in Farbe und Schrifttyp voneinander abhebt. Das Programm erkennt an der Dateierweiterung.

Entsprechend sind Einrückungen und Ähnliches automatisch eingestellt, so dass Sie immer einen Block auch in derselben Spalte beginnen können.

Wenn Sie an die Stelle hinter einer Klammer kommen, wird die zugehörige Klammer kurz durch ein rotes Quadrat markiert. Wenn Sie also einmal einen Sachverhalt nicht als selbsterklärend erachten, finden Sie dort sicherlich Rat.

Und nun kann ich Ihnen nur raten, die gezeigten Beispiel immer wieder zu laden, zu verändern und zu erweitern -- und natürlich auch eigene Programme zu schreiben. Sicher werden Sie dabei immer wieder mit den verschiedensten Fehlermeldungen des Compilers konfrontiert werden.

Aber nur auf diese Weise werden Sie mit der Zeit seine Arbeitsweise verstehen und zu einem korrekten Programmierstil gelangen, mit dem Sie Ihre eigentlichen Aufgaben angehen können. Zusammenfassung Die wichtigsten Aspekte dieses Abschnitts waren: Als Argument erwartet dieser zumindest den Namen der Quelltext-Datei.

Die Option -g bewirkt, dass Informationen für den Debugger hinzugefügt werden. Was ist an folgendem Aufruf falsch? Klassen und Objekte Auf den Seiten ff. Klassendeklaration und -definition Eine Klasse ist zunächst einmal ein von Ihnen definierter Datentyp.

Sie müssen sie deklarieren, damit sie dem Compiler bekannt ist. Eine Klasse hat im Allgemeinen folgende Bestandteile: Zugriffsbeschränkungen für ihre Elemente: Diese legen fest, ob andere Klassen auf ein Element dieser Klasse zugreifen dürfen oder nicht siehe Seite.

Diese Funktionen werden aufgerufen, wenn ein Objekt dieser Klasse erzeugt beziehungsweise vernichtet wird. Durch einen Konstruktor kann beispielsweise Speicherplatz für das Objekt bereitgestellt und es selbst initialisiert werden.

Hier sind die eigentlichen Daten gespeichert. Attribute werden wie Variablen deklariert. Sie können bei jedem Objekt andere Werte haben. Attribute können einen Standarddatentyp haben oder selbst wieder ein Objekt einer anderen Klasse sein. Methoden können auf die Attribute und Zustände des Objekts zugreifen. Deklaration Die Syntax zur Klassendeklaration besteht aus dem Schlüsselwort class , dann dem Namen der Klasse, gefolgt von den Klassenbestandteilen; diese sind von geschweiften Klammern eingeschlossen.

Kommen wir auf unser Beispiel von Seite zurück. Neu ist der Typ string ; dies ist eine Klasse für Zeichenketten, die wir später noch öfter verwenden werden.

In den Zeilen 13 und 14 stehen die Deklarationen des Konstruktors und des Destruktors. Dies sind Funktionen, die immer dann automatisch aufgerufen werden, wenn ein Objekt von dieser Klasse erzeugt beziehungsweise vernichtet wird. Aber dazu in einem der nächsten Abschnitte mehr. Definition und Bereichsoperator Wahrscheinlich ist Ihnen nach dieser Überschrift nicht ganz klar, was jetzt schon wieder auf Sie zukommt.

Was ist denn der Unterschied zwischen Deklaration und Definition einer Klasse? Man macht ihn hauptsächlich an den Methoden fest: Eine Deklaration dient dazu, den neuen Datentyp dem Compiler bekannt zu machen. Dabei müssen Sie die Typen aller Attribute sowie die Schnittstellen Köpfe der Methoden angeben, also auch welche Parameter eine Methode benötigt und von welchem Datentyp der Rückgabewert ist.

Wie die Methoden implementiert sind, müssen Sie hier noch nicht angeben. Kurz gefasst bedeutet dies: Auf diese Weise können Sie ein Stück Prozessabstraktion verwirklichen: Andere, die Ihre Klasse verwenden wollen, müssen nur die Header-Datei, also die Deklaration kennen; die Definition kann im Verborgenen bleiben.

Wie wir später sehen werden, ist die Realität leider etwas komplizierter. Es ist nämlich auch erlaubt, die Definition einer Methode gleich inmitten der Klassendeklaration zu schreiben. Im Augenblick können Sie aber bei dieser Trennung bleiben. Dazu verwenden Sie den Bereichsoperator:: Später Seite werden wir die Möglichkeiten der Positionen, an denen Sie Deklaration und Definition unterbringen können, noch genauer fassen.

Ist sie erst einmal definiert, gilt sie als Datentyp. Wir können sie dann wie jeden anderen Datentyp verwenden und Variablen davon bilden. Man spricht bei einer Variablen, die als Typ eine Klasse hat, von einem Objekt dieser Klasse oder auch von einer Instanz der Klasse auch wenn das eine nicht ganz korrekte Übersetzung des englischen Begriffs instance ist.

Zugriffsbeschränkungen Zugriffsbeschränkungen regeln, ob andere Klassen auf ein Klassenelement zugreifen dürfen oder nicht. Dabei gibt es folgende Möglichkeiten: Die nachfolgenden Elemente und Methoden unterliegen keiner Zugriffsbeschränkung, sie können daher beliebig verändert beziehungsweise aufgerufen werden. Es gibt auch noch eine dritte Ebene, protected , die wir aber erst später -- ab Seite -- behandeln wollen. Wenn Sie eine Zugriffsbeschränkung angeben, gilt diese für alle nachfolgenden Elemente -- solange, bis eine andere Beschränkung kommt oder die Klassendeklaration endet.

Fehlt in einer Klasse die Festlegung der Zugriffsbeschränkung ganz, so werden alle Elemente als private behandelt. In obigem Beispiel haben wir die beiden Zugriffsebenen in folgender Form verwendet: Wenn Sie in Ihrem Programm etwa die Anweisung schreiben: Anders sieht es in den Methoden der Klasse selbst aus.

Hier dürfen Sie stets auf alle Elemente zugreifen, natürlich auch auf die privaten. Betrachten Sie folgende Methode: Die Zugriffsbeschränkung gilt auf der Ebene der Klassen und nicht der Objekte. Wenn in einer Methode ein Objekt derselben Klasse auftaucht, so hat die Methode Zugang zu allen Elementen des Objekts, öffentliche wie private, zum Lesen wie zum Schreiben.

Freunde Wenn Sie einmal in die Lage geraten, dass Sie ohne die Zugriffsmöglichkeit auf private Elemente einer anderen Klasse nicht weiterkommen, deutet das meistens auf einen Designfehler hin. Allerdings gibt es in der Praxis durchaus Fälle, bei denen ein Verzicht auf den Zugriff einen sehr viel umständlicheren und damit meist langsameren Code mit sich bringen würde.

Damit teilen Sie dem Compiler innerhalb der Klassendeklaration mit, welche anderen Elemente vollen Zugriff auf die Klasse erhalten. Funktionen einzelne Methoden anderer Klassen ganze Klassen Im Englischen packt man diese Eigenschaft in ein leicht zweideutiges Wortspiel: Only friends may touch your private things.

Dieses Vorrecht räumer wir damit aber nur der B:: Andere Methoden von B sofern vorhanden haben kein Zugriffsrecht auf A:: Zudem haben wir in einer erneuten Vorwärts-Deklaration auf eine Klasse C hingewiesen, die an anderer Stelle deklariert werden kann, die aber hier das volle Zugriffsrecht auf A erhalten hat.

Zusammenfassung Aus diesem Abschnitt sollten Sie sich merken: Klassen haben folgende Merkmale: Um eine Methode als zu einer bestimmten Klasse zugehörig zu kennzeichnen, verwendet man den Bereichsoperator:: Ist eine Klasse einmal definiert, kann sie wie jeder andere Datentyp verwendet werden.

Zugriffsbeschränkungen regeln, ob andere Klassen auf ein Klassenelement zugreifen dürfen oder nicht. Alle auf public folgenden Elemente unterliegen keiner Zugriffsbeschränkung, während alle unter private nur innerhalb der Klasse selbst zugänglich sind.

Das Schlüsselwort friend erlaubt es Funktionen, einzelnen Methoden anderer Klassen oder sogar ganzen Klassen, die Zugriffsbeschränkungen zu umgehen. Beachten Sie dabei die Zugriffsbeschränkungen und die erforderlichen Methoden. Was versteht man unter einer Vorwärts-Deklaration? Wozu wird sie benötigt? Die Möglichkeit, Funktionen zu bilden, ist ein herausragendes Merkmal einer Programmiersprache.

Ganz allgemein versteht man unter einer Funktion einen in sich geschlossenen Programmteil, der eine bestimmte Aufgabe erfüllt. Eine Funktion, die zu einer Klasse gehört, nennt man Methode. Betrachten wir folgendes Beispiel: Vorher noch ein typografischer Hinweis: Es hat sich eingebürgert, in Büchern zwei Klammern hinter Bezeichner zu setzen, die sich auf eine Funktion beziehen, zum Beispiel in Sätzen wie: Mit add erreichen Sie die Addition zweier Ganzzahlen.

Das sagt noch nichts über Art und Umfang der Argumentliste aus, sondern soll Sie lediglich daran erinnern, dass es dabei um eine Funktion und nicht um eine Variable geht. Ich will mich auch in diesem Buch daran halten. Manchmal ist es aber auch gar nicht nötig oder sinnvoll, dass eine Funktion überhaupt einen Rückgabewert hat. In diesem Fall geben Sie als Typ void an.

Was macht man nun mit einem solchen Wert? Der Programmteil, der die Funktion aufruft, kann diese an allen Stellen einsetzen, wo er sonst eine Variable oder Konstante angeben würde in obiger Form allerdings nur dort, wo lediglich der Wert benötigt wird , also etwa: Selbst wenn eine Funktion einen Wert zurückgibt, müssen Sie ihn nicht beachten. Sie dürfen auch schreiben: Argumentliste Eine Funktion kann immer nur auf den Daten arbeiten, die ihr lokal vorliegen.

Von diesen Parametern auch Argumente genannt können Sie keinen, einen oder mehrere angeben, die Sie dann durch Kommas trennen. Wenn Sie eine Funktion ohne Argumente schreiben wollen, lassen Sie den Bereich zwischen den beiden runden Klammern einfach leer -- denn die Klammern müssen Sie stets schreiben!

Ansonsten geben Sie für jeden Parameter seinen Datentyp und einen Namen an, unter dem er in der Funktion bekannt sein soll. Dieser Name kann vollkommen anders sein, als der im Hauptprogramm beim Aufruf verwendete. Funktionskörper Hier stehen die Anweisungen, die bei einem Aufruf der Funktion ausgeführt werden.

Man kann darüber streiten, wie lang Funktionen sein sollten. Es gibt Experten, die fordern, dass eine Funktion aus nicht mehr als 50 Zeilen bestehen dürfe, sonst werde sie unleserlich. Es gibt jedoch in der Praxis immer wieder Fälle, in denen längere Funktionen sinnvoll sind.

Bei der objektorientierten Programmierung werden Sie allerdings ohnehin wesentlich mehr Funktionen beziehungsweise Methoden verwenden, die im Durchschnitt wesentlich kürzer sind als bei der prozeduralen Programmierung.

Innerhalb des Funktionskörpers können Sie die Funktionsparameter wie normale Variablen verwenden; zusätzlich können Sie natürlich auch noch lokale Variablen definieren. Sie dürfen sogar die Funktion selbst wieder aufrufen; man spricht dann von einer rekursiven Funktion -- aber das ist ein eigenes Thema.

Return-Anweisung Die Anweisungen im Funktionskörper werden so lange abgearbeitet, bis das Programm auf das Ende der Funktion oder eine return -Anweisung trifft. Diese erfüllt einen doppelten Zweck: Sie legen fest, welchen Wert die Funktion an das Hauptprogramm zurückliefern soll.

Das kann eine Variable sein oder ein Ausdruck, eine Konstante oder der Rückgabewert einer anderen Funktion wobei Letzteres als schlechter Stil gilt. Der Typ des angegebenen Werts muss jedoch in jedem Fall mit dem deklarierten Rückgabetyp übereinstimmen.

Sie beenden die Funktion und kehren zum Hauptprogramm zurück. Jede return -Anweisung -- sei sie nun am Ende oder irgendwo inmitten des Funktionskörpers -- markiert das Ende der Abarbeitung der Funktion und den Rücksprung an die Stelle, von der aus die Funktion aufgerufen wurde. Sie können also die Funktion schon beenden, bevor alle Anweisungen ausgeführt sind, zum Beispiel wenn eine bestimmte Bedingung erfüllt ist.

Ist der Rückgabetyp void , muss am Ende der Funktion keine return -Anweisung stehen auch nicht das Schlüsselwort return , wie in folgendem Beispiel: Der Prototyp Bevor Sie eine Funktion verwenden können, müssen Sie dem Compiler zunächst mitteilen, dass es eine Funktion dieses Namens gibt, wie viele und welche Parameter sie hat und welchen Typ sie zurückliefert.

Dies geschieht mit einem so genannten Prototyp der Funktion. Der Prototyp sieht genauso aus wie die Funktion selbst bis auf den Funktionskörper; dieser fehlt und wird durch ein einfaches Semikolon ; ersetzt. Es ist sogar erlaubt, die Namen der Argumente wegzulassen und nur ihre Typen anzugeben. Folgendes Beispiel zeigt den Umgang mit Prototypen: In main werden sie dann aufgerufen Zeilen und ab Zeile 17 definiert.

Wenn das Programm aber weiter wächst, kann der Verlass auf die Reihenfolge schnell zu Problemen führen. Am besten verwenden Sie für jede Quelltextdatei eine eigene Header-Datei.

Hier ist dies haupt. Gegenüber dem obigen Code müssen Sie bei der Implementierung in getrennten Dateien dort noch einen include -Befehl für die Header-Datei mit den Funktionsprototypen einfügen, also: Beides zusammen bezeichnet man gelegentlich auch als Signatur der Funktion. Damit erhalten Sie die Freiheit, zwei Funktionen gleichen Namens zu verwenden, die sich aber in ihren Argumenten unterscheiden.

Man bezeichnet das auch als Überladung des Funktionsnamens. Wir hatten oben Seite eine Funktion add definiert, um zwei Ganzzahlen zu addieren. Nun kann man natürlich auch Dezimalbrüche addieren; das deckt unsere Funktion aber nicht ab. Wir definieren also eine zweite Funktion mit demselben Namen! Gerade wenn zwei Funktionen wie unsere beiden add dieselbe Anzahl von Argumenten haben und zudem nur Standardtypen verwenden, ist es für den Compiler machmal schwer, eindeutig die passende Funktion zu einem bestimmten Aufruf zu finden.

Betrachten Sie etwa folgenden Code und überlegen Sie sich vor dem Weiterlesen, welche Funktion in den jeweiligen Zeilen aufgerufen wird: Sehen wir uns die Aufrufe also genauer an: Bei den Zeilen 8 und 9 ist alles klar: Hier werden nur double - beziehungsweise int -Werte als Parameter übergeben, so dass die jeweiligen Funktionen aufgerufen werden. In Zeile 10 ist das zweite Argument ein 'a' , also vom Typ char.

Dieser Typ zählt auch zu den Ganzzahl-Werten und kann nach int konvertiert werden. Es kommt also die int,int -Variante zum Einsatz. In Zeile 11 kommt es zum Streitfall: Zum einen könnte die Zahl 3. Was soll der Compiler also tun? Da er ratlos ist, gibt er eine Fehlermeldung aus: Hier müssen wir als Programmierer eingreifen. Eine Lösung sehen Sie in Zeile Durch die explizite Umwandlung von c nach float wird die Eindeutigkeit wiederhergestellt.

Ein ganz ähnliches Problem findet sich auch in Zeile Sie sehen daran, dass es im Grunde keinen Unterschied macht, ob Sie echte Zahlen als Argumente einsetzen im Fachjargon literale Konstanten oder Variablen.

Die Möglichkeiten zur impliziten Konvertierung und damit zum Auftreten von Doppeldeutigkeiten sind stets vorhanden. Genauso wie Funktionen können Sie auch Methoden in Klassen überladen.

Folgendes Programm gibt die übergebenen Argumente auf den Bildschirm aus: Die for -Schleife in Zeile 7, zu deren Syntax wir später noch genauer kommen Seite , durchläuft einfach alle Argumente vom ersten bis zum letzten, wie in argc angegeben.

Wenn Sie sehr umfangreiche Listen von Kommandozeilenargumenten verarbeiten wollen, empfehle ich Ihnen den Einsatz der Bibliotheksroutine getopt , die ich Ihnen auf Seite vorstellen werde. Schauen wir uns ein Beispiel an: Die Funktion printNumber kann mit einem, mit zwei oder mit drei Parametern aufgerufen werden, jedoch nur in der angegebenen Reihenfolge.

Somit sind folgende drei Aufrufe identisch: Alle Parameter mit Vorgabewerten müssen am Ende der Argumentliste stehen. Es darf also nach ihnen kein Argument ohne Vorgabewert folgen. Beim Aufruf müssen Sie ebenfalls die Reihenfolge der Parameter beachten. Bei mehreren Argumenten mit Vorgabewert bedeutet das, dass Sie nicht willkürlich mal ein Argument angeben, beim nächsten aber auf den Vorgabewert vertrauen dürfen.

Bei obigem Beispiel müssen Sie also immer, wenn Sie fillchar setzen wollen, auch fillsize setzen. Es ist Ihnen sicher jetzt schon klar, dass Vorgabewerte für Parameter zuweilen recht praktisch sein können.

Hat etwa eine Funktion oder eine Methode! Aber auch aus Sicht der etwas abstrakteren Objektorientierung sind Vorgabewerte willkommen -- denn sie sorgen für Erweiterbarkeit. Nun kommen Sie in die Situation, ein weiteres Argument zu der Funktion hinzufügen zu müssen.

In einer Programmiersprache ohne die Möglichkeit von Vorgabewerten müssten Sie nun an allen Stellen, an denen updateDisplay aufgerufen wird, Ihr Programm ändern und einen Standardwert hinzufügen. Neu zu schreibende Aufrufe können indessen den zusätzlichen Parameter nutzen.

Sie können damit ein und denselben Speicherplatz unter zwei verschiedenen Namen im Programm ansprechen. Jede Modifikation der Referenz ist eine Modifikation der Variablen selbst -- und umgekehrt. Wenn Ihnen das jetzt etwas abstrakt vorkommt, befinden Sie sich in guter Gesellschaft. Daher gleich ein Beispiel: Wenn Sie ihn an anderer Stelle verwenden, hat er leider eine völlig andere Bedeutung. Eine Referenz muss stets bei ihrer Deklaration sofort initialisiert werden.

Es ist also nicht möglich, eine Referenz erst einmal zu deklarieren, um ihr dann später etwas zuzuweisen. Eine Referenz einer Variable kann später nicht auf eine andere Variable umgesetzt werden.

Falls Sie also einen Aliasnamen für verschiedene Variablen hintereinander benötigen, müssen Sie jeweils eine eigene Referenz verwenden. Der Datentyp der Referenz und der Variablen müssen übereinstimmen. Selbst wenn zwei Typen durch implizite Konvertierung ineinander umgewandelt werden können, ist es nicht zulässig, eine Referenz mit einer Variablen eines anderen Typs zu initialisieren.

Innerhalb einer Funktion verwendet man nicht allzu häufig Referenzen. Manchmal kommt man aber zu ziemlich langen Ausdrücken, insbesondere bei Objekten, deren Attribute wieder Objekte sind und so weiter; dann kann der Einsatz von Referenzen für solche verschachtelten Attribute die Lesbarkeit deutlich erhöhen. Die häufigste Anwendung ist aber die Übergabe von Funktionsparametern als Referenz, wie wir sie im nächsten Abschnitt kennen lernen werden. Parameterübergabe als Referenz Bisher waren wir davon ausgegangen, dass eine Funktion die Parameter, die sie erhält, nur verwendet -- also liest -- und nicht verändert.

In einigen Fällen aber will man gerade, dass die Funktion die Parameter verändert. Hat die Funktion beispielsweise mehrere Ergebniswerte, so reicht der eine return -Wert zum Austausch der Information nicht aus. Sehen wir uns etwa folgende Funktion an: Die Antwort ist leider nein. Es findet zwar ein Austausch statt, aber das Hauptprogramm erfährt davon nichts.

Die Variablen, die dieser Funktion übergeben werden, haben hinterher immer noch dieselben Inhalte wie vorher. Ganz anders sieht die Lage aus, wenn die Parameter als Referenzen übergeben werden auf Englisch call by reference genannt. Dann sind diese nämlich nicht im Unterprogramm eigenständige Speicherstellen, die nach dem Rücksprung wieder freigegeben werden, sondern Aliasnamen für die Variablen im Hauptprogramm.

Jede Änderung, die das Unterprogramm, also die Funktion, an den Parametern vornimmt, wirkt unmittelbar auf die im Hauptprogramm definierten und der Funktion übergebenen Variablen. Um das zu erreichen, müssen wir obige Funktion nur ein klein wenig abändern: Konstanten und Referenzen Wenn Sie einer Funktion ein Objekt per Wert übergeben im Fachenglisch call by value genannt , wird eine Kopie des Objekts angelegt, mit dem die Funktion dann arbeitet.

Daher wäre es besser, diese als Referenz zu übergeben, denn dabei bekommt die Funktion nur den Verweis auf die Speicherstelle, was sehr schnell und einfach abgewickelt werden kann. Das Problem dabei ist jedoch, dass damit der Funktion das Recht eingeräumt wird, das Objekt in jeder beliebigen Form zu verändern, was ja meist nicht beabsichtigt ist.

Um dieses Problem in den Griff zu bekommen, verwenden Sie das Schlüsselwort const. Damit können Sie jede Variable und jede Referenz als konstant deklarieren, so dass sie nicht mehr verändert werden kann. Wenn Sie also in Ihrem Programm einen bestimmten Wert mehrfach benötigen, sollten Sie ihn an zentraler Stelle zum Beispiel global in der Hauptdatei des Projekts oder in einer entsprechenden Header-Datei als Konstante definieren und später dann nur noch diesen Namen für den entsprechenden Wert verwenden.

Ein Vorteil dabei ist, dass Sie später, wenn Sie das Programm mit einem anderen Wert übersetzen wollen, diesen nur einmal ändern müssen und ihn im Allgemeinen auch sofort finden. Was hilft uns das Schlüsselwort const beim Problem der Parameterübergabe? Sie bauen die Funktion so, dass sie nicht eine einfache Referenz als Argument erhält, sondern eine konstante Referenz. Dann hat sie beispielsweise folgende Form: Am Aufruf sieht man nicht, ob da ein Objekt, eine Referenz oder eine konstante Referenz übergeben wird.

Vielleicht ist Ihnen aufgefallen, dass ich die ganze Zeit von Objekten gesprochen habe, während vorher immer allgemeiner von Variablen die Rede war. Der Grund dafür ist, dass konstante Referenzen im Allgemeinen nur für Objekte benutzt werden. Konstante Methoden Obwohl es eigentlich nichts mit Referenzen zu tun hat, wollen wir uns kurz noch mit dem Thema Konstante Methoden beschäftigen.

Nachdem Sie jetzt wissen, wie Sie einer Funktion ein konstantes Objekt übergeben, ist Ihnen vermutlich noch nicht so ganz klar, was Sie in der Funktion mit dem Objekt machen dürfen und was nicht. Und wenn es Ihnen schon nicht klar ist, werden Sie es dem Compiler sicher ebenfalls kaum begreiflich machen können. Die Attribute dürfen bei einem konstanten Objekt nur gelesen, aber nicht überschrieben werden. Was ist aber mit den Methoden? Wenn Sie eine Methode eines Objekts aufrufen, wissen Sie ja nicht, was darin genau passiert.

Möglicherweise finden darin ja Modifikationen an den Attributen statt -- genau das, was wir mit dem konstanten Objekt ja verhindern wollten. Ich kann Sie beruhigen: Solche Methoden darf die Funktion nicht aufrufen, das verhindert bereits der Compiler. Hier kommt das Schlüsselwort const abermals zum Einsatz. Damit eine Methode für ein konstantes Objekt aufgerufen werden darf, müssen Sie diese in der Klasse als const deklarieren.

Dieses const muss nach der Argumentliste und vor dem Semikolon beziehungsweise dem Methodenkörper stehen. Wenn Deklaration und Definition einer Methode getrennt sind, muss const bei beiden stehen, sonst fasst der Compiler die Definition als eine andere Signatur auf. Sehen wir uns das an einem Beispiel an: Fragen Sie sich besser bei jeder Methode, ob diese eine Veränderung des Objekts bewirken soll oder nicht; im letzteren Fall deklarieren Sie sie stets als const.

Somit werden Sie übrigens auch daran gehindert, die stets fehlerträchtigen Nebeneffekte zu programmieren -- schon mancher Benutzer einer Klasse hat sich gewundert, warum sein Objekt nach einem Lesezugriff plötzlich verändert war. Zugriffsroutinen Sie erinnern sich sicherlich, dass ich Ihnen die Datenabstraktion als wichtiges Prinzip der objektorientierten Programmierung vorgestellt habe auf Seite. Schlagen Sie am besten nochmals Abbildung 2.

Dort wird gezeigt, dass im Idealfall andere Objekte nur über Nachrichten auf die Daten eines Objekts zugreifen können. Nachrichten werden aber als Methoden des Empfängers implementiert. Für die Datenelemente Ihrer Klasse empfiehlt sich folgende Vorgehensweise: Deklarieren Sie alle Datenelemente als private und nur Methoden als public.

Um den Bezug zum Attribut herzustellen sowie gleichzeitig die Bedeutung zu illustrieren, verwenden viele Programmierer auch ich für die Namen dieser Methoden immer die Vorsilben get beziehungsweise set , gefolgt vom Namen des Attributs.

Deklarieren Sie alle Lesemethoden als const. In unserer Beispielklasse haben Sie bereits solche Methoden gesehen: Inline-Funktionen Was passiert eigentlich bei einem Funktions- oder Methodenaufruf?

Grob gesprochen wird der Programmfluss angehalten, die Parameter in einen speziellen Bereich genannt Stack kopiert, der Ausgangspunkt gemerkt und an den Beginn der Funktion gesprungen. Nach deren Abarbeitung werden ihre lokalen Variablen wieder gelöscht, der Stack aufgeräumt und das Hauptprogramm fortgesetzt. Bei sehr kurzen Funktionen, wie sie bei der objektorientierten Programmierung häufiger als anderswo auftauchen zum Beispiel als Zugriffsmethoden , dauert die Verwaltung des Aufrufs länger als die Abarbeitung selbst.

Abhilfe bieten da so genannte inline -Funktionen. Durch die Angabe dieses Schlüsselworts vor einer Funktion erreichen Sie, dass für die Funktion kein Aufruf im oben genannten Sinn erzeugt wird, sondern der Funktionskörper direkt an die Stelle eingefügt wird eben in line, in der Zeile. Es ist dann also keine echte Funktion mehr, sondern nur ein Stück Code im Hauptprogramm. Erfahrenen C-Programmierern kommt jetzt sicher der Gedanke an Makros. Auch diese bewirken eine Ersetzung schon durch den Präprozessor ; allerdings können bei diesen keine Datentypen für die Argumente definiert werden.

Bei inline -Funktionen bleibt die Prüfung des Argumenttyps sowie der sonstigen Syntax genauso erhalten, als ob es sich um eine tatsächliche Funktion handeln würde.

Deklaration als inline Um eine Funktion als inline zu deklarieren, schreiben Sie dieses Schlüsselwort zur Definition, und zwar als Allererstes, also noch vor den Rückgabetyp, zum Beispiel: Sie können die Behandlung einer Funktion als inline nicht erzwingen.

Allgemein sollten Sie komplexere Funktionen, die eine Reihe von Anweisungen sowie Schleifen und Ähnliches enthalten, nicht als inline deklarieren. Selbst wenn der Compiler dies akzeptiert und umsetzt, besteht dadurch die Gefahr, dass Ihr Code stark aufgebläht und die Optimierung behindert wird. Die Implementation einer als inline deklarierten Funktion sollte immer in einer Header-Datei stehen. Wenn Sie nämlich im Header den Prototyp angeben und erst in der Implementationsdatei die Funktion als inline kennzeichnen, wird bei der Verwendung in anderen Dateien jeweils ein normaler Aufruf erzeugt, was spätestens beim Linken zu Problemen führt.

Klassenmethoden als inline Zugriffsmethoden von Klassen sind die idealen Kandidaten für die inline -Deklaration. Sie sind meist sehr kurz, werden aber ziemlich oft benötigt. Mit dem jetzigen Wissen können Sie sich auch für eine andere Stelle entscheiden, an der Sie Ihre Methode implementieren. Deklaration und Definition innerhalb der Klassendeklaration. Wenn Sie eine Methode direkt innerhalb der Klassendeklaration implementieren, also auch den Funktionskörper angeben, wird diese automatisch als inline behandelt, auch wenn das entsprechende Schlüsselwort fehlt.

Das ist bei sehr kurzen Methoden ein oder zwei Zeilen durchaus üblich. Deklaration und Definition als inline -Funktion in der Header-Datei. Wenn Sie Ihre Methode als inline gelten lassen wollen, sollten Sie sie aus oben beschriebenen Gründen innerhalb der Header-Datei implementieren. Diese Möglichkeit wählt man oft bei etwas längeren Methoden mit mehr als zwei Zeilen , die aber noch sehr einfach sind, also beispielsweise keine Schleifen enthalten, oder wenn man auf Klassenelemente zugreifen muss, die erst später deklariert werden.

Deklaration in der Header-Datei und Definition in der Implementationsdatei. Jede davon wird dann als echte Funktion behandelt, die einmal zu Objektcode übersetzt und später dann nur noch dazugelinkt werden muss. Sehen wir uns die drei Varianten in der Praxis an. Die erste Möglichkeit führt etwa zu folgendem Code: Die zweite Variante hat beispielsweise folgende Form: Anders sieht dies beim dritten Fall aus.

Hier findet sich im Include-File nur noch: Zusammenfassung In diesem Abschnitt haben Sie eine Menge gelernt.

Die wichtigsten Aspekte waren: Funktionen liefern immer einen Wert zurück, es sei denn, die Funktion ist als void definiert. Eine Funktion kann einen oder mehrere Parameter haben.

Jede Funktion muss vor ihrer Verwendung deklariert werden: Sie ist der Einstiegspunkt in das Programm. Der Rückgabewert von main kann von der Shell, die das Programm startet, ausgewertet werden. Daher können Sie zwei Funktionen gleichen Namens mit unterschiedlichen Argumenten definieren überladene Funktionen.

Sie können für einzelne Argumente einer Funktion Vorgabewerte engl. Eine Referenz ist ein Aliasname für eine Variable. Jede Modifikation der Referenz führt zu einer Modifikation der Variablen und umgekehrt.

Übergibt man einer Funktion eine Referenz, so kann diese den Inhalt der übergebenen Variablen ändern. Um zu vermeiden, dass der gesamte Datenbestand eines Objekts bei einem Funktionsaufruf kopiert wird, und um zu verhindern, dass die Funktion den Inhalt des Objekts ändern kann, übergibt man eine konstante Referenz auf das Objekt an die Funktion.

Ist eine Funktion oder Methode als inline deklariert, wird bei der Kompilierung der Aufruf vollständig durch den Funktionskörper ersetzt. Das bietet sich besonders bei Zugriffsmethoden auf Klassenelemente an. Übungsaufgaben Beantworten Sie folgende Fragen: Wie viele Rückgabewerte kann eine Funktion haben?

Was ist die Signatur einer Funktion? Kann eine Klasse zwei Methoden gleichen Namens enthalten, die sich nur in ihren Rückgabewerten unterscheiden? Was stimmt bei folgendem Programm nicht: Eine rationale Zahl wird dargestellt durch mit ganzzahligen und , wobei. Addition und Multiplikation sind wie bekannt definiert. Schreiben Sie eine Klasse Rational , die eine rationale Zahl repräsentiert. Diese soll über die Rechenfunktionen add , sub , mult und div verfügen, wobei der Bruch stets vollständig gekürzt gespeichert werden soll.

Die Klasse habe folgende Struktur: Konstruktoren und Destruktoren Wenn Sie bereits mit anderen Programmiersprachen gearbeitet haben, wird Ihnen das Konzept der Konstruktoren und Destruktoren zunächst etwas merkwürdig vorkommen -- handelt es sich doch um Funktionen, die aufgerufen werden, ohne dass ihr Aufruf im Programmtext steht!

Mit der Zeit werden Sie aber die Abläufe verstehen und merken, dass auch da kein Geheimnis dahinter steckt. Besondere Eigenschaften Konstruktoren haben einige besondere Eigenschaften, die sie von allen anderen Methoden unterscheiden: Aufrufe von Konstruktoren werden automatisch in das Programm eingefügt.

Jedes Mal, wenn ein Objekt erzeugt wird und die Klasse über einen entsprechenden Konstruktor verfügt, wird dieser aufgerufen. Explizite Konstruktoraufrufe gibt es also nicht.

Konstruktoren tragen denselben Namen wie die Klasse. Alle anderen Namen können keine Konstruktoren bezeichnen. Konstruktoren haben keine Rückgabewerte auch nicht void. Sie dürfen keinen Rückgabetyp bei der Deklaration eines Konstruktors angeben und auch keine void -Anweisungen mit Argument verwenden. Ein einfaches, schon klassisches Beispiel für einen selbst definierten Datentyp ist ein Datum , das einen Tag im Kalender repräsentiert. Ich will in diesem Abschnitt eine solche Klasse mit Ihnen aufbauen, um die verschiedenen Arten von Konstruktoren deutlich zu machen.

Standardkonstruktor englisch default constructor. Dieser wird bei jeder Erzeugung eines Objekts der Klasse verwendet, wenn kein anderer Konstruktor in Frage kommt. Dieser kann beliebige Argumente haben und wie eine Methode überladen werden.

Es können also mehrere Konstruktoren mit verschiedenen Argumentlisten existieren. Auch Vorgabewerte für die Argumente sind erlaubt. Dieser dient dazu, ein Objekt dieser Klasse mit einem anderen derselben Klasse zu initialisieren. Er erhält dazu als Argument eine konstante Referenz auf das Objekt. Dieser hat nur ein Argument und dient dazu, einen anderen Datentyp in die Klasse als Typ gesehen umzuwandeln.

Im Folgenden wollen wir die verschiedenen Konstruktoren genauer betrachten. Standardkonstruktor Der Standardkonstruktor, der leider viel zu oft auch im Deutschen mit dem englischen Ausdruck default constructor bezeichnet wird, hat keine Argumente. Er wird immer dann aufgerufen, wenn ein Objekt dieser Klasse ohne weitere Angaben erzeugt wird. Bei unserem Beispiel lautet die Deklaration: Ich sprach oben davon, dass eine der Aufgaben des Konstruktors sei, Speicherplatz für die Attribute bereitzustellen.

Vielleicht fragen Sie sich nun, warum Sie davon in dieser Methode nichts sehen. Ebenso wie bei lokalen Variablen -- unabhängig davon, ob ihr Typ einfach oder eine Klasse ist -- kann das System selbstständig ermitteln, wie viel Speicher die Attribute benötigen, und diesen entsprechend reservieren.

Auch das kann innerhalb eines Konstruktors geschehen. Doch dazu kommen wir später noch. Jetzt sehen wir uns an, wo der Konstruktor aufgerufen wird. In einem Hauptprogramm steht beispielsweise: Natürlich können Sie auch mit der Klasse arbeiten und Objekte davon erzeugen, wenn diese keinen Konstruktor hat.

Allerdings sind dann die Attribute in einem unbestimmten Zustand -- genauso wie Variablen, die Sie nur deklariert, aber nicht initialisiert haben. Ich möchte Ihnen daher empfehlen, bei allen Ihren Objekten zumindest einen Standardkonstruktor zu definieren. Da er beispielsweise keinen Rückgabewert hat, werden mögliche Fehler nicht ohne Weiteres vom Programm bemerkt.

Richten Sie im Zweifelsfall lieber eine zusätzliche Methode ein, in der dann kritische Initialisierungen vorgenommen werden können. Hintergrund Die Einfügung des Konstruktoraufrufs klappt übrigens auch bei Verschachtelungen. Wenn Sie beispielsweise eine Klasse haben wie: Auch Vorgabewerte für die Parameter sind erlaubt. Wir wollen unsere Klasse um eine vollständige Initialisierung erweitern sowie um eine, die nur den Tag enthält.

Die Einstellungen kehren nicht automatisch zu den Standardeinstellungen zurück. Wird für die langfristige Archivierung elektronischer Dokumente verwendet. Kompatible Dateien müssen Informationen enthalten, die die Druckbedingung beschreiben, für die sie vorbereitet wurden.

In diesem Fall ist die Qualität des Inhalts von höchster Priorität. Die verwendeten Schriftarten werden in Form von Untergruppen eingebettet und die Transparenz wird beibehalten bei Dateitypen, die transparenzfähig sind. Dieser Optionssatz verwendet Komprimierung, Neuberechnung und eine relativ niedrige Bildauflösung. In diesem Fall können Sie bzw. Ihr Druckdienstleister benutzerdefinierte Vorgaben erstellen.

Adobe PDF-Vorgaben werden als. Verwenden Sie zur Suche nach weiteren. Bereits vorhandene Einstellungen werden bei Bedarf überschrieben.

Im Hintergrundaufgaben-Bedienfeld wird der Fortschritt des Exportvorgangs angezeigt. Durch Auswahl einer Region ändert sich die Sprache und ggf. Dokumente werden auf Handheld-Geräten nicht korrekt angezeigt. Dokumente mit komplexen Formatierungen sind für sehbehinderte Leser schwer zugänglich. Exportieren in PDF für den Druck. Geben Sie einen Namen und Speicherort für die Datei an.

Führen Sie einen der folgenden Schritte durch:. Wenn bestimmte Ebenen nicht zusammengeführt werden sollen, geben Sie ihnen in jedem Buchdokument eindeutige Namen. Exportieren eines Buches in PDF.