Erstellen eines C ++ - Namespace in Header und Quelle (cpp)

86

Gibt es einen Unterschied zwischen dem Umschließen von Header- und CPP-Dateiinhalten in einen Namespace oder dem Umschließen nur des Headerinhalts und dem anschließenden Verwenden des Namespace in der CPP-Datei?

Mit Unterschied meine ich jede Art von Leistungseinbußen oder leicht abweichenden Semantiken, die Probleme verursachen können oder alles, was ich beachten muss.

Beispiel:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

Wenn es keinen Unterschied gibt, welche Form wird bevorzugt und warum?

links77
quelle

Antworten:

36

Der Namespace ist nur eine Möglichkeit, die Funktionssignatur zu entstellen, damit sie nicht in Konflikt geraten. Einige bevorzugen den ersten Weg und andere bevorzugen die zweite Version. Beide Versionen haben keinen Einfluss auf die Leistung der Kompilierungszeit. Beachten Sie, dass Namespaces nur eine Entität zur Kompilierungszeit sind.

Das einzige Problem, das bei der Verwendung von Namespace auftritt, besteht darin, dass wir dieselben verschachtelten Namespace-Namen haben (dh) X::X::Foo. Dies führt zu mehr Verwirrung mit oder ohne Verwendung von Schlüsselwörtern.

vprajan
quelle
54

Der Unterschied zwischen "Namespace X" und "Namespace X verwenden" besteht im ersten darin, dass sich alle neuen Deklarationen unter dem Namensraum befinden, im zweiten nicht.

In Ihrem Beispiel gibt es keine neue Deklaration - also keinen Unterschied, also keinen bevorzugten Weg.

Roee Gavirel
quelle
Das hängt vom Projekt und vom Stil ab. Oft gibt es einen Hauptnamespace für eine Ladung von Dateien in einem Modul, und der zweite Stil ist sinnvoll.
Nicholas Wilson
8

Es gibt keine Leistungseinbußen, da das Ergebnis das gleiche sein könnte, aber das Einfügen Ihres FooNamespace führt implizit zu Mehrdeutigkeiten, falls Sie Foos in verschiedenen Namespaces haben. Sie können Ihren Code tatsächlich fubar bekommen. Ich würde empfehlen, die Verwendung usingfür diesen Zweck zu vermeiden .

Und du hast einen Streuner {danach using namespace;-)

Michael Krelin - Hacker
quelle
Ich würde es nicht als streunend bezeichnen, da es zum Abschluss ganz }am Ende passt . Allerdings würde ich dieses Paar Zahnspangen als überflüssig bezeichnen;)
blubberdiblub
@blubberdiblub, die Frage wurde bearbeitet, wenn Sie die Originalversion überprüft haben, würden Sie es Streuner nennen ;-)
Michael Krelin - Hacker
1

Wenn auch der zweite kompiliert wird, sollte es keine Unterschiede geben. Namespaces werden zur Kompilierungszeit verarbeitet und sollten die Laufzeitaktionen nicht beeinflussen.

Aber für Designprobleme ist der zweite schrecklich. Auch wenn es kompiliert wird (nicht sicher), macht es überhaupt keinen Sinn.

holgac
quelle
1
Ich glaube nicht, dass es kompiliert wird, aber nicht, weil es einen Unterschied gibt, sondern weil es einen Streuner gibt {;-)
Michael Krelin - Hacker
Der Unterschied ist, dass Foo :: TheFunc () im globalen Namespace deklariert ist, während es im Namespace X definiert ist.
Bert-Jan
1

Foo :: TheFunc () befindet sich im VS-Fall nicht im richtigen Namespace. Verwenden Sie 'void X :: Foo :: TheFunc () {}', um die Funktion im richtigen Namespace (X) zu implementieren.

Bert-Jan
quelle
Die Frage ist etwas alt, aber wissen Sie, welche Konsequenzen dies hat? dh werden Sie auf Probleme mit der Art und Weise stoßen, wie sein VS-Fall die Funktionen im Namespace deklariert, sie aber außerhalb des Namespace definiert?
Adam Goodwin
1

Wenn Sie nur den .h-Inhalt einschließen, müssen Sie ihn mit dem Namespace ... in die cpp-Datei schreiben, andernfalls arbeiten Sie jedes Mal am gültigen Namespace. Normalerweise verpacken Sie sowohl CPP- als auch H-Dateien, da sonst das Risiko besteht, Objekte aus einem anderen Namespace zu verwenden, was zu vielen Problemen führen kann.

AlexTheo
quelle
0

Ich denke, das Richtige hier ist, den Namespace für das Scoping zu verwenden.

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}
Kjetil Hvalstrand
quelle
0

Wenn Sie versuchen, Variablen von einer zur anderen zu verwenden, würde ich empfehlen, sie zu externalisieren und dann wie folgt in der Quelldatei zu initialisieren:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}
dieser Fuchs
quelle