C++-Programmierung: Namensräume

Aus Wikibooks
Alte Seite
Diese Seite gehört zum alten Teil des Buches und wird nicht mehr gewartet. Die Inhalte sollen in das neue Buch einfließen: C++-Programmierung/ Inhaltsverzeichnis.

Definieren[Bearbeiten]

Grundlegend[Bearbeiten]

Namensräume grenzen den Gültigkeitsbereich besser ab. Dies ermöglicht mannigfaltige Konzepte. Im Folgenden wird in Codebeispielen eine Funktion in Namensräumen definiert. In Namensräumen lässt sich aber auch jegliche sonstige, weitere Definition/Deklaration verpacken.

Für den schnellen Einstieg hier ein Beispiel:

void f() { ; }  // Funktion auffindbar im globalen Namensraum
namespace MTF            
{ 
  void f() // Funktion auffindbar im Namensraum MTF
  {
    throw std::exception("f - ausgelöst");
  };
}

Im Folgenden der Aufruf:

void g()
{
  f();                       // f() aus globalem Namensraum wird aufgerufen
  MTF::f();                  // f() aus Namensraum MTF wird aufgerufen
  using namespace MTF;       // Namensraum MTF wird sichtbar gemacht
  f();                       // f() aus Namensraum MTF wird in diesem Fall aufgerufen
}

Verschachtelt[Bearbeiten]

Namensräume lassen sich auch beliebig verschachteln.

namespace MTF
{ 
  namespace XYZ
  {
    void f() // Funktion auffindbar im Namensraum MTF::XYZ
    {
      throw std::exception("f - ausgelöst");
    };
  }
}


Bei späterer Verwendung kann dann die Funktion f() aus dem Unternamensraum des Namensraums MTF::XYZ mit MTF::XYZ::f() verwendet werden. Dies bietet Vorteile um umfangreiche Abschnitte in Bibliotheken oder großen Programmen gegeneinander abzugrenzen und um die gleichen Bezeichner in unterschiedlichen Namensräumen zu verwenden.

Aliasnamen[Bearbeiten]

Namensräume können Aliasnamen erhalten. Sinn macht dies z.B. bei langen Namen:

namespace Die_geheime_Codesammlung_meiner_tollen_Firma
{ 
  void f() // Funktion auffindbar im Namensraum Die_geheime_Codesammlung_meiner_tollen_Firma
  {
    throw std::exception("f - ausgelöst");
  };
}

namespace MTF = Die_geheime_Codesammlung_meiner_tollen_Firma; // Für Alle, die lieber MTF:: schreiben

Wiedereröffnung[Bearbeiten]

Namensräume können an jeder Stelle – außerhalb von Funktions- und Klassendefinitionen – geöffnet und geschlossen werden und somit in beliebig vielen Quelldateien erweitert werden. Das Öffnen und Schließen muss immer einzeln erfolgen, Konstrukte wie namespace MTF::XYZ { const int a = 3; } um den Namensraum MTF::XYZ zu erweitern sind nicht möglich.

namespace MTF
{ 
  void f() // Funktion auffindbar im Namensraum MTF
  {
    throw std::exception("f - ausgelöst");
  };
}

void Irgendwas::OnX() { .. }; // Etwas anderes dazwischen

namespace MTF
{
  const int v = 19;
  void g()
  {
    f();  // Aufruf von f() - natürlich aus Namensraum MTF (in dem wir uns gerade befinden)
  };
}

Wiedereröffnung kann, wie hier ersichtlich, genutzt werden, um einen vorhandenen Namensraum zu erweitern und um auf alle Definitionen darin zuzugreifen, ohne eine Bereichsauflösung z.B. MTF::f() oder using-Deklaration zu verwenden. Wenn ein Namensraum nicht von Ihnen selber angelegt wurde, ist allerdings große Vorsicht geboten.

Verwenden[Bearbeiten]

using-Deklaration[Bearbeiten]

Im Programm aus der ersten Lektion kommen der Name für die Standardausgabe std::cout und der Name für den Zeilenvorschub std::endl vor. Beiden sind die Zeichen std:: vorangestellt. Dabei handelt es sich um einen Namensraum (namespace), in diesem Fall den Namensraum std der C++-Standardbibliothek. Um nicht jedes Mal std:: schreiben zu müssen, können Sie mit Hilfe der using-Deklaration die Namen bekannt machen. Anschließend kann std:: weggelassen werden:

#include <iostream>
int main()
{
  using std::cout;             // macht std::cout bekannt
  using std::endl;             // macht std::endl bekannt
  cout << "Hallo!" << endl;    // hier kann std:: weggelassen werden
}

Wie eine Variablen-Deklaration gilt using für den jeweiligen Block.

using-Direktive[Bearbeiten]

Wollen Sie nicht nur einzelne Namen, sondern einen ganzen Namensraum bekannt machen, verwenden Sie die Direktive using namespace:

Da durch den Gebrauch von using namespace Namensbereiche ihren ursprünglichen Sinn, der Schutz vor Merfachbenennung, verlieren, wird es als besserer Programmierstil angesehen, wenn man die Elemente einzeln mit der using-deklaration einbindet.

#include <iostream>
#include <string>
int main()
{
  using namespace std;        // macht alles aus dem Namensraum std bekannt
  string text("Peter!");
  cout << text << endl;
  text = "Hans";
  cout << text << endl;
}