Namespaces in C++
Namensräume wurden erschaffen, um Namenskonflikte zu unterbinden. In fast allen Tutorials hast du auf einen Namespace zugegriffen! Die Befehle cout und endl liegen im Namensraum std. Der Zugriff sieht folgendermassen aus: namensraum::element. Die 2 Doppelpunkte sind dabei der Scope Operator, mit dem man in denn Namensraum rein gehen kann. Ein Element was in einem Namensraum liegt, und auf ein anderes Element im gleichen Namensraum zugreifen will, muss denn Namensraum und denn Scope Operator nicht angeben. Ein Element kann z. B. eine Funktion, Klasse, Datenstruktur, Variable, Konstante oder ein weiterer Namensraum sein.
Der Zugriff auf einen Namespace
Ein Namensraum kann auch mit dem Schlüsselwort "using" als Standart gesetzt werden.
Das bedeutet, dass bei einem Aufruf nicht der Name vom Namensraum mit dem Scope Operator (::) vor den Befehl notiert werden müssen.
Datei:
Quelldateien/main.cpp- #include <iostream> // std::cout, std::endl, std::cin
- #include <stdlib.h> // EXIT_SUCCESS
-
- using namespace std;
-
- int main(void)
- {
- cout << "count Aufruf aus dem Namensraum std" << endl;
-
- cin.get();
- return EXIT_SUCCESS;
- }
Es können auch nur bestimmte Elemente aus einem Namespace als Standart gesetzt werden.
Datei:
Quelldateien/main.cpp- #include <iostream> // std::cout, std::endl, std::cin
- #include <stdlib.h> // EXIT_SUCCESS
-
- using std::cout;
- using std::endl;
-
- int main(void)
- {
- cout << "cout und endl Aufruf aus dem Namespace std" << endl;
-
- std::cin.get(); // Wurde nicht mit using angegeben, daher "std::"
- return EXIT_SUCCESS;
- }
Definieren von einem Namespace
Im folgenden Beispiel werden wir einen Namensraum erstellen, denn wir dann separat in eine Datei auslagern. Nachdem ein neues Projekt mit der nötigen main.cpp Datei erstellt worden ist, erstellen wir nun eine neue Headerdatei Namens "namensraum.h".
Datei:
Headerdateien/namensraum.h- #ifndef NAMENSRAUM_H
- #define NAMENSRAUM_H
- namespace namensraum
- {
- class klassenname
- {
- public:
- void methodenname(void); // Methode für Klasse im Namespace deklarieren
- };
-
- void funktionsname(void); // Funktion im Namespace deklarieren
-
- namespace weiterer_namensraum
- {
- void funktionsname(void); // Funktion im Namespace::Namespace deklarieren
- }
- }
- #endif
Da die Headerdatei mehrmals eingebunden werden kann, stellen wir mit #ifndef zuerst sicher, dass sie nicht schon eingebunden worden ist und deklarieren die Symbolische Konstante NAMENSRAUM_H.
Ein Namensraum wird mit dem Schlüselwort namespace eingeleitet. Danach wird der Name für den Namensraum (hier namensraum) festgelegt und die geschweiften Klammern umschliessen alles was darin alles enthalten ist. Im Beispiel wird im Namensraum eine Klasse deklariert mit einer Methode. Danach kommt eine einzelne Funktion und zum Schluss wird im Namensraum ein weiterer Namensraum (hier weiterer_namensraum) erstellt. Dieser Namensraum hat ebenfalls nur eine Funktion.
Als nächstes muss noch die Quelldatei namensraum.cpp unter Quelldateien erstellt werden, in der der Namensraum mit seinem Inhalt noch definiert wird.
Datei:
Quelldateien/namensraum.cpp- #include "namensraum.h"
- namespace namensraum
- {
- void klassenname::methodenname(void) // Methode für Klasse im Namespace definieren
- {
- std::cout << "\"klassenname::methodenname()\" aus dem Namespace \"namensraum\" aufgerufen!\n";
- }
-
- void funktionsname(void) //Funktion im Namespace definieren
- {
- std::cout << "Funktion \"funktionsname()\" aus dem Namespace \"namensraum\" aufgerufen!\n";
- }
-
- namespace weiterer_namensraum // Namespace im Namespace definieren
- {
- void funktionsname(void)
- {
- std::cout << "Funktion \"funktionsname()\" aus dem Namespace \"namensraum::weiterer_namensraum\" aufgerufen!\n";
- }
- }
- }
Hiermit ist der Namensraum fertig definiert und deklariert. Jetzt müssen wir die main.cpp etwas anpassen.
Datei:
Quelldateien/main.cpp- #include <iostream> // std::cout, std::endl, std::cin
- #include <stdlib.h> // EXIT_SUCCESS
- #include "namensraum.h"
-
- int main(void)
- {
- namensraum::klassenname *cls = (new namensraum::klassenname);//Instanz in Pointer laden
- cls->methodenname();
-
- namensraum::funktionsname(); // Direkter Funktionsaufruf im Namespace
-
- namensraum::weiterer_namensraum::funktionsname(); // Direkter Funktionsaufruf im Namespace::Namespace
-
- std::cin.get();
- return EXIT_SUCCESS;
- }
Wie das Beispiel zeigt, werden 2 identische Funktionen mit dem gleichen Namen aufgerufen. Der Namespace hat in diesem Fall eine Namenskollision verhindert, indem er beide Funktionen in verschiedene "Ebenen" verfrachtet hat.