Wahrscheinlich ein Duplikat, aber nicht leicht zu suchen ...
Bei einem Header wie:
namespace ns1
{
class MyClass
{
void method();
};
}
Ich habe method()
in der CPP-Datei verschiedene Definitionen gesehen:
Version 1:
namespace ns1
{
void MyClass::method()
{
...
}
}
Version 2:
using namespace ns1;
void MyClass::method()
{
...
}
Version 3:
void ns1::MyClass::method()
{
...
}
Gibt es einen "richtigen" Weg, dies zu tun? Sind diese "falsch", weil sie nicht alle dasselbe bedeuten?
c++
coding-style
namespaces
Mr. Boy
quelle
quelle
Antworten:
Version 2 ist unklar und nicht leicht zu verstehen, da Sie nicht wissen, zu welchem Namespace
MyClass
gehört, und es ist nur unlogisch (Klassenfunktion nicht im selben Namespace?)Version 1 ist richtig, da sie zeigt, dass Sie im Namespace die Funktion definieren.
Version 3 ist auch deshalb richtig, weil Sie den
::
Bereichsauflösungsoperator verwendet haben, um auf denMyClass::method ()
im Namespace zu verweisenns1
. Ich bevorzuge Version 3.Siehe Namespaces (C ++) . Dies ist der beste Weg, dies zu tun.
quelle
namespace N {struct X { void f(); }; X operator==( X const &, X const & ); }
jetzt in der cpp-Datei mit der using- Anweisung haben, könnenvoid X::f() {}
Sie dieX operator==(X const&, X const&)
Elementfunktion als definieren. Wenn Sie jedoch definieren , definieren Sie einen anderen Operator als den in der Kopfzeile definiert (Sie müssen dort entweder 1 oder 3 für die freie Funktion verwenden).5 Jahre später und ich dachte, ich würde das erwähnen, was beide gut aussieht und nicht böse ist
quelle
Ich verwende Version 4 (unten), weil sie die meisten Vorteile von Version 1 (Knappheit der resoektiven Definition) und Version 3 (maximal explizit) kombiniert. Der Hauptnachteil ist, dass die Leute nicht daran gewöhnt sind, aber da ich es als technisch überlegen gegenüber den Alternativen betrachte, macht es mir nichts aus.
Version 4: Verwenden Sie die vollständige Qualifizierung mithilfe von Namespace-Aliasnamen:
In meiner Welt verwende ich häufig Namespace-Aliase, da alles explizit qualifiziert ist - es sei denn, dies kann nicht (z. B. Variablennamen) oder es ist ein bekannter Anpassungspunkt (z. B. swap () in einer Funktionsvorlage).
quelle
outer
undinner
definiert als Namensräume in anderen Header - Dateien bereits?Version 3 macht die Zuordnung zwischen der Klasse und dem Namespace auf Kosten einer größeren Eingabe sehr explizit. Version 1 vermeidet dies, erfasst jedoch die Zuordnung zu einem Block. Version 2 neigt dazu, dies zu verbergen, daher würde ich dies vermeiden.
quelle
Googles C ++ Style Guide diktiert Ihre Version 1, jedoch ohne Einrückung.
quelle
Ich wähle Num.3 (auch bekannt als die ausführliche Version). Es ist mehr Tippen, aber die Absicht ist genau für Sie und den Compiler. Das Problem, das Sie so wie es ist gepostet haben, ist tatsächlich einfacher als die reale Welt. In der realen Welt gibt es andere Definitionsbereiche, nicht nur Klassenmitglieder. Ihre Definitionen sind nicht nur mit Klassen sehr kompliziert - da ihr Bereich nie wieder geöffnet wird (im Gegensatz zu Namespaces, globalem Bereich usw.).
Num.1 Dies kann mit anderen Bereichen als Klassen fehlschlagen - alles, was wieder geöffnet werden kann. Sie können also mit diesem Ansatz eine neue Funktion in einem Namespace deklarieren, oder Ihre Inlines werden möglicherweise über ODR ersetzt. Sie benötigen dies für einige Definitionen (insbesondere für Vorlagenspezialisierungen).
Num.2 Dies ist sehr fragil, insbesondere in großen Codebasen. Wenn sich Header und Abhängigkeiten verschieben, kann Ihr Programm nicht kompiliert werden.
Num.3 Dies ist ideal, aber es gibt viel zu tippen - was Sie beabsichtigen, um etwas zu definieren . Dies tut genau das, und der Compiler greift ein, um sicherzustellen, dass Sie keinen Fehler gemacht haben. Eine Definition stimmt nicht mit ihrer Deklaration usw. überein.
quelle
Es stellt sich heraus, dass es nicht nur um "Codierungsstil" geht. Num. 2 führt zu einem Verknüpfungsfehler beim Definieren und Initialisieren einer extern deklarierten Variablen in der Header-Datei. Schauen Sie sich ein Beispiel in meiner Frage an. Definition der Konstante im Namespace in der CPP-Datei
quelle
Alle Wege sind richtig und jeder hat seine Vor- und Nachteile.
In Version 1 haben Sie den Vorteil, dass Sie den Namespace nicht vor jede Funktion schreiben müssen. Der Nachteil ist, dass Sie eine langweilige Identifikation erhalten, insbesondere wenn Sie mehr als eine Ebene von Namespaces haben.
In Version 2 machen Sie Ihren Code sauberer. Wenn jedoch mehr als ein Namespace im CPP implementiert ist, kann einer direkt auf die Funktionen und Variablen des anderen zugreifen, wodurch Ihr Namespace unbrauchbar wird (für diese CPP-Datei).
In Version 3 müssen Sie mehr eingeben und Ihre Funktionslinien sind möglicherweise größer als der Bildschirm, was für Designeffekte schlecht ist.
Es gibt auch eine andere Art, wie manche Leute es benutzen. Es ähnelt der ersten Version, jedoch ohne Identifizierungsprobleme.
Es ist so:
Es liegt an Ihnen zu entscheiden, welche für jede Situation besser ist =]
quelle
#ifdef
Klausel einfügen.#define OPEN_NS(X)
ich denke, es ist ein wenig nützlich, aber nicht wirklich ... Ich habe keine Einwände gegen Makros, aber das scheint ein bisschen OTT zu sein. Ich denke, Dietmar Kühls Ansatz ist besser für verschachtelte Namespaces.