C++-Programmierung: Namensräume

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;
}