Bereiche und Dateien
In C und C++ wird Programmcode mittels geschweifter Klammern { } in Bereiche eingeteilt, welche im englischen als scopes
bezeichnet werden. Bereiche definieren grundsätzlich die Zusammengehörigkeit von Anweisungen und Symbolen und kommen bei verschiedenen Elementen der Sprachen C und C++ zum Einsatz. Bereiche können ineinander verschachtelt werden, wobei der äusserste Bereich durch die Implementations-Datei begrenzt ist und als der globale Bereich
bezeichnet wird. Mittels des Preprozessors können weitere Header-Dateien eingebunden werden.
|
|
Details
Bereiche werden stets mittels geschweifter Klammern { } umfasst und innerhalb eines Bereiches können wiederum beliebig viele Bereiche enthalten sein. Bereiche können somit ineinander verschachtelt werden, wobei die Klammerung wohlgeformt sein muss (Jede schliessende Klammer muss mittels einer eindeutigen öffnenden Klammer eingeleitet worden sein). Um Bereiche visuell besser hervorzuheben, rückt man Programmcode innerhalb eines Bereiches üblicherweise um einen Tab-Schritt ein.
Bereiche haben insbesondere zwei Funktionen: Die Strukturierung von Code und die Festlegung der Sichtbarkeit von Symbolen.
Code-Strukturierung
Die eine Aufgabe von Bereichen ist das Unterteilen von Programmcode in ausführbare Codeblöcke: Die in geschweiften Klammern enthaltenen Anweisungen werden als zusammengehörig betrachtet. Grundsätzlich kann ein Bereich im Programmtext einfach durch die Verwendung von öffnenden und schliessenden geschweiften Klammern inmitten des Programmtextes definiert werden. Diese Methode wird jedoch in dieser rohen Form kaum verwendet. Viel häufiger wird diese Methode im Zusammenhang mit Kontrollstrukturen verwendet. Durch die Angabe eines Bereiches bei einer Kontrollstruktur werden vom Compiler sämtliche Anweisungen innerhalb des Bereiches als zusammengehörig betrachtet. Details können bei den Anweisungsblöcken nachgelesen werden.
Bei der Definition einer Funktion werden ebenfalls die geschweiften Klammern verwendet, um festzulegen, dass jeglicher Programmcode, der sich innerhalb des Funktions-Bereiches befindet, zu der betreffenden Funktion gehört.
Symbole
Die zweite (und weitaus wichtigere) Aufgabe von Bereichen ist die Regelung der Sichtbarkeit von Symbolen über verschiedene Bereiche hinweg.
Grundsätzlich gilt für einen Bereich: Alle Symbole, welche innerhalb eines Bereiches deklariert oder definiert werden, sind für Programmtext, welcher sich ausserhalb des Bereiches befindet, nicht direkt sichtbar. Programmtext, welcher sich innerhalb eines Bereiches befindet, kann jedoch auf Symbole ausserhalb des Bereiches zugreifen. Diese Basisregeln sind genauso gültig, wenn die Bereichsklammerung ineinander verschachtelt ist, die Beziehung somit über mehr als eine Bereichsgrenze hinaus geht: Von aussen nach innen ist nichts sichtbar, von innen nach aussen alles.
Innerhalb eines Bereiches darf ein Symbol nur einmal definiert werden (mit Ausnahme der Funktionsüberladungen in C++). Symbolnamen in anderen Bereichen (ausserhalb, sowie innerhalb) werden nicht in Betracht gezogen. Während der Programmausführung wird grundsätzlich das Symbol des innersten Bereiches angesprochen, sofern sich gleichnamige Symbole in Bereichen ausserhalb befinden. Ein Symbol, welches sich bei der Programmausführung ausserhalb des aktuellen Bereiches befindet, wofür jedoch im aktuellen Bereich ein gleichnamiges Symbol existiert, kann in C nicht angesprochen werden. In C++ kann es mittels Angabe des zugehörigen Namespaces angesprochen werden.
Elemente von class-, struct-, enum- und union-Typen können mittels Angabe einer Variable mit dem entsprechenden Typ angesprochen werden. Die Sichtbarkeit von Symbolen kann in C++ bei Klassen und Structs zusätzlich durch die Keywords public, protected und private gesteuert werden.
Dateien: Der globale Bereich
Programmcode von C und C++ wird in einfache Textdateien geschrieben. Diese Dateien werden als Quell-Dateien oder auf Englisch als Source-Files bezeichnet. Es wird grundsätzlich zwischen Implementations-Dateien und Header-Dateien unterschieden. Heutige Entwicklungssysteme nehmen automatisch jede Implementatins-Datei als Startpunkt für den Compiler an. Die Header-Dateien werden vom Compiler nicht direkt angesprochen, sondern sie werden mittels des Preprozessors in die zu kompilierende Implementations-Datei eingebunden.
Header-Dateien haben normalerweise die Dateiendung .h und beinhalten hauptsächlich Deklarationen. In gewissen Fällen finden sich innerhalb von Header-Dateien auch Definitionen, beispielsweise bei der Verwendung von Templates.
Implementations/Dateien haben in C die Dateiendung .c und für C++ hat sich mit der Zeit die Dateiendung .cpp durchgesetzt. Dennoch sind auch Dateiendungen wie .cc oder .c++ möglich und teilweise noch im Umlauf. In Implementationsdateien werden hauptsächlich Definitionen geschrieben. Durch Einbindung von Header-Dateien kann zusätzliche Funktionalität, welche sich in anderen Dateien befindet, eingebunden werden
Für jede Implementationsdatei nimmt der Compiler zu Beginn den globalen Bereich an. Alle Symbole, welche in diesem nicht-{}-umklammerten Bereich deklariert oder definiert werden, sind globale Symbole und können überall angesprochen werden. Im globalen Bereich befindet sich immer auch die main-Funktion. Diejenige Datei, welche die main-Funktion beinhaltet wird als die Primäre Quelldatei
bezeichnet.
In C++ kann der globale Bereich explizit mittels des global-Bereichs-Operators :: angesprochen werden.
Im globalen Bereich darf grundsätzlich kein ausführbarer Programmcode stehen. Initialisierungen sind jedoch erlaubt. In C sind diese jedoch auf konstante Werte beschränkt. In C++ können auch Konstruktoren oder Funktionen für Initialisierungen aufgerufen werden.
In der modernen Programmierung sind globale Symbole verpönt, allerdings sind sie nicht verboten. So werden sie nach wie vor von Programmierern benutzt, wenn beispielsweise ein kleines Programm geschrieben werden muss, welches mehr auf Funktionalität denn auf durchdachte Strukturierung getrimmt ist (quick and dirty). Ausserdem ist zu bemerken, dass Compiler und Linker selbst teilweise globale Variablen implizit definieren, wodurch das Programm erst lauffähig wird (siehe dazu Runtime-System).
Namespaces
In C++ können einige Bereiche benannt werden, was dann als Namespace
bezeichnet wird. Die deutsche Bezeichnung Namensraum
wird auf dieser Seite nicht verwendet. In C existieren keine Namespaces. Ein Namespace kann mittels des namespace-Keywords definiert werden, wobei sämtliche, sich innerhalb der darauffolgenden geschweiften Klammern befindlichen deklarierten oder definierten Symbole in dem angegebenen Namespace befinden. Ein Symbol, welches sich innerhalb eines Namespaces befindet, kann mittels des Bereichs-Operators :: angesprochen werden. Man beachte, dass auch Namespaces selbst Symbole sind und sich somit selbst innerhalb eines Namespaces befinden können.
Klassen legen anhand des angegebenen Klassen-Namens automatisch einen Namespace fest, wobei sämtliche Symbole, die innerhalb dieser Klasse deklariert oder definiert werden, sich in diesem Namensraum befinden. Dasselbe gilt in C++ auch für Structs.