2012-06-07 5 views
14

Angenommen, ich habe eine Funktion deklariert (oder Klasse, spielt keine Rolle) in einer Header-Datei, die einen Teil von Namespace foo ist:Best Practices: Namespace verwenden oder Namespace erneut öffnen?

namespace foo 
{ 
    void bar(); 
    … 
} 

Für eine lange Zeit, die ich die Namespace Wiedereröffnung habe, als ich die Funktion in einer CPP-Datei wurde die Definition:

namespace foo 
{ 
void bar() 
{ 
    doSomething(); 
    … 
} 
} 

das ist, weil ich es auf diese Weise gelernt und es wurde in einem Projekt, das ich arbeite verwendet. Ich habe nie wirklich obwohl darüber, bis vor kurzem, als ich auf ein Projekt gestolpert, die stattdessen das using-Direktive verwendet:

using namespace foo; 

void bar() 
{ 
    doSomething(); 
    … 
} 

Endlich gibt es eine Möglichkeit, den vollständigen Namen verwenden. Ich finde es ziemlich langweilig, besonders wenn Klassen mit vielen Mitgliedern involviert sind. Meiner Meinung nach macht es wenig Sinn, wenn der gesamte Inhalt der Datei Teil eines Namensraums ist.

void foo::bar() 
{ 
    doSomething(); 
    … 
} 

Also meine Frage ist, welche sollte bevorzugt werden und warum? Vor allem in Bezug auf die ersten beiden Optionen (mit dem Namespace directory vs. reopen).

+3

Ich würde sagen, es ist eine Frage des persönlichen Geschmacks ist.Ich selbst verwende eine Mischung aus den ersten und letzten Ihrer Alternativen. –

+5

Ich stimme zu, dass es eine persönliche Vorliebe ist. 'foo :: bar' ist repetitiv, aber übergreifbar, obwohl das irrelevant ist, wenn die Leute Ihre Quelle immer nur mit einer IDE suchen. –

+2

Es ist wie die Frage, ob es besser ist, Tabulatoren oder 4 Leerzeichen zu verwenden. ** Schweiß nicht die kleinen Sachen. ** :) – LihO

Antwort

13

Ich denke, der sauberste Weg, um die Namensraum-Öffnung wieder, und ich habe die Argumente habe es zu unterstützen:

  • mit Ihrer zweiten Option, mit der using Richtlinie genügt es, dass Sie nicht klar ist, Implementieren einer Methode in diesem Namespace. Sie könnten auch eine freie Funktion implementieren, die etwas aus dem Namespace verwendet.
  • Die dritte Option wird normalerweise zur Implementierung von Klassenmemberfunktionen verwendet. Wenn Sie direkt in die Datei cpp schauen, ist es nicht klar, dass Sie eine Funktion aus einem Namespace implementieren, wenn Sie nicht wissen, dass Namespace existiert. Das erste, was Ihnen in den Sinn kommt, ist, dass Sie eine Klassenmitgliedsfunktion implementieren.
  • der erste ist der klarste. Sie öffnen den Namespace und definieren darin eine Funktion. Die Funktion ist Teil des Namespace und dies ist die Implementierung.
+0

Ihr zweiter Punkt scheint zu sagen, "Ich mache nicht X, deshalb ist das erste, was mir in den Sinn kommt, Y". Y kommt nicht unbedingt zuerst in den Köpfen von Leuten, die X machen, also verschwindet das Problem, sobald du der Konvention folgst. Wenn Sie den Unterschied zwischen Namespace-Namen und Klassennamen nicht erkennen können, sollten Sie auch bessere Namen ;-p. –

+0

@SteveJessop Ich denke nicht, dass das ein gültiger Punkt ist. 'X :: foo()' ist die * einzige * Möglichkeit, eine Klassenmethode zu definieren (außer inline). Während für Namespaces Sie eine Alternative haben. Warum also zwei Stile verwenden, um verschiedene Dinge darzustellen, wenn Sie verschiedene Stile mit klarer Absicht verwenden können? –

+1

Es scheint hier ein grundlegendes Axiom zu sein, dass es äußerst wichtig ist, verschiedene Dinge so unterschiedlich wie möglich aussehen zu lassen. Ich denke, andere Dinge können wichtiger sein, daher akzeptiere ich dieses Axiom nicht (wenn ich es tun würde, würde ich C verwenden, da es keine Funktionsüberladung hat). –

6

Auch wenn using namespace die faulste (und daher die verlockendste) Lösung ist, ist es oft keine gute Idee. Abgesehen davon, was Luchian sagt, dass Funktionsdeklarationen mehrdeutig sind (jemand, der neu im Projekt ist, würde nicht wissen, ob das eine Standalone-Funktion oder eine im Namespace ist) und die Tatsache, dass Sie später einen Namen in den Namespace eingeben Jetzt habe ich einen anderen Grund, warum ich vorschlagen würde, die dritte Methode zu verwenden.

Mit der dritten Methode geben Sie Ihren Code mehr Konsistenz. Wenn A in B ist, würden Sie es immer mit A::B definieren. Wenn A eine Klasse und B eine Funktion in der Klasse ist, würden Sie type A::B(args) schreiben. Wenn A eine Klasse und B ein statisches Element ist, würden Sie erneut type A::B = value schreiben. Jetzt ist A ein Namensraum, aber es ist immer noch das gleiche Konzept: B ist innerhalb A definiert, daher ist es konsistenter, wieder A::B zu verwenden.

(Es gibt einen zusätzlichen Bonus von Such-Fähigkeit, wenn Ihr Editor Vim ist zum Beispiel)