2015-08-18 14 views
8

In einer C++ Implementierung-Datei, habe ich die Möglichkeit, so etwas wie zu schreiben:Header-Dateien, ohne explizit Namespace Schreiben

name::space::ClassName::someFunction(int param) { 
    // impl 
} 

statt

namespace name { 
    namespace space { 
     ClassName::someFunction(int param) { 
      // impl 
     } 
    } 
} 

, die ich sehr bequem und besser lesbar zu finden. Kann das irgendwie auch in Header-Dateien verwendet werden? Etwas wie folgt aus:

class name::space::ClassName { 
    // declarations 
}; 

statt

namespace name { 
    namespace space { 
     class ClassName { 
      // declarations 
     }; 
    } 
} 

Wenn so etwas wie dies möglich ist, dann unter welchen Bedingungen? Ich könnte mir vorstellen, dass man müsste uns darauf, die Namespace deklarieren uns darauf, die Klassen im Namensraum wie folgt erklären:

namespace name { 
    namespace space { 
     class ClassName; 
    } 
} 

bevor diese in der Lage zu verwenden:

class name::space::ClassName { 
    // declarations 
}; 

in einer Header-Datei .

Aber irgendwie kann ich das nicht zur Arbeit 1]. Ist es überhaupt möglich? Was mich stört ist, dass ich bei verschachtelten Namespaces 2 Tabulatoren einrücken muss, bis ich meine Klasse deklarieren kann. Ich möchte diesen Platz in meinen Header-Dateien verwenden, aber ich möchte die Tabs nicht weglassen, da dies gegen die "alles in geschweiften Klammern muss einmal Tabbed" -Rule sein würde (ich weiß nicht, ob es da ist ein tatsächlicher Name für das. Wenn es, Entschuldigung meine Ignoranz, ich kenne keine: S

1] Das Problem, das ich konfrontiert wurde, war nicht mit der Frage verbunden.Der Ansatz funktioniert tatsächlich, aber es hat Nachteile (siehe akzeptierte Antwort).

+4

'mit verschachtelten Namespaces Ich habe einrücken 2 tabs' Sie nicht wirklich __have__ zu, es geht um Ihre Codierung Konvention. Zum Beispiel fügen wir keinen zusätzlichen Einzug für verschachtelte Namespaces hinzu, wo ich arbeite. – SingerOfTheFall

+3

eine Mischform dieser tabbing Regel ist 'Namespace-Name verwenden {Namensraum-Raum {' in einer Zeile und den Rest Einzug mit nur einem Tab, dann endet mit '}}' – stijn

+0

@SingerOfTheFall Welcher (= Einrücken nicht für Namespaces) I halte eine sehr vernünftige Sache für möglich. – Angew

Antwort

6

Wenn Sie einfach nicht die Namespace Klammern möchten Ihre Klassendefinition umhüllen, können Sie sicher, dass erreichen, indem er den Namespace woanders nur mit der Klassendeklaration innerhalb definieren. Auf diese Weise können Sie mit so etwas wie diese kommen:

#ifndef MYCLASS_H 
#define MYCLASS_H 

namespace ClassNamespace { class MyClass; }; 

class ClassNamespace::MyClass 
{ 
public: 
    MyClass(); 
    ~MyClass(); 
    void a(); 
private: 

}; 

#endif // MYCLASS_H 

für den Header und diese:

#include "MyClass.h" 

#include <iostream> 

using namespace std; 

ClassNamespace::MyClass::MyClass() 
{ 
} 

ClassNamespace::MyClass::~MyClass() 
{ 
} 

void ClassNamespace::MyClass::a() 
{ 
    cout << "hello"; 
} 

für die Umsetzung.

Wie Sie sehen können, ist der Namensraum nicht die Klassendefinition einschließen, nur seine Erklärung.

Als abschließende Bemerkung, ich weiß persönlich nicht, warum Sie dies tun wollen würde oder denken, es schöner zu lesen aussieht. Ich würde persönlich viel lieber sehen, die Namespace die Klassendefinition sowie die Funktionsdefinitionen zu kapseln. Aber vielleicht habe ich schon das ungerade ganze ...

+2

Es ist schwer zu erklären, warum ich es besser mag. Ich finde es viel besser lesbar, wenn ich das Tabbing bei Verwendung der gekapselten Namespaces nicht weglassen möchte. Zu deiner Antwort: Also würde das eigentlich funktionieren? Ich mag diesen Ansatz besser. Wenn ich einen dedizierten Header verwende, in dem alle Namespaces für das Projekt definiert sind, kann ich sie besser dokumentieren (an nur einer Stelle und nicht an jedem Ort, an dem ein Namespace-Schlüsselwort verwendet wird). Der Nachteil auf der anderen Seite ist offensichtlich; Sie müssten eine andere Datei pflegen und sie überall einfügen ... – CharlyDelta

+1

Es ist sicherlich eine interessante Idee. Auf diese Weise können Sie im Wesentlichen einen Ort haben, an dem Sie alle Ihre Klassen und die zugehörigen Namespaces anzeigen können. Oder vielleicht ein Namespace pro Datei. Ich glaube wirklich nicht, dass es Standardkonventionen sind, aber es ist sicher interessant. Ich glaube nicht, dass ich etwas dagegen hätte. – nicholaschiasson

+0

Update: Obwohl ich die Idee mochte, muss ich zugeben, dass das Speichern der Namespaces in einer separaten Datei nicht praktikabel ist. Wenn eine Klasse gelöscht, ersetzt oder umbenannt wird, gibt es keine Garantie dafür, dass der Entwickler sich daran erinnert, die unnötige Forward-Deklaration der Klasse zu entfernen. Dies wird schließlich die Namespace-Datei aufblähen ... Wie auch immer, ich habe meinen Code so geändert, wie Sie es vorgeschlagen haben, mit dem Inline Namespace und der Klasse Forward Deklaration über der Klasse. Dies ist der beste Kompromiss für mich, so dass ich meine Einzug-Verwendung beibehalten kann und nicht zweimal einrücken muss, wenn ich Namespaces verschachtelt habe. Danke für alle Antworten und Hilfe – CharlyDelta

1

Nein, es ist nicht möglich. die einzige Möglichkeit, definiert ein Namespace mit dem namespace Schlüsselwort in Kombination mit geschweiften Klammern.

7.3.1 Namespace-Definition [namespace.def]

1 Die Grammatik für einen Namespace-Definition ist

namespace-name: 
     original-namespace-name 
     namespace-alias 
    original-namespace-name: 
     identifier 
    namespace-definition: 
     named-namespace-definition 
     unnamed-namespace-definition 
    named-namespace-definition: 
     original-namespace-definition 
     extension-namespace-definition 
    original-namespace-definition: 
     inlineopt namespace identifier { namespace-body } 
    extension-namespace-definition: 
     inlineopt namespace original-namespace-name { namespace-body } 
    unnamed-namespace-definition: 
     inlineopt namespace { namespace-body } 
    namespace-body: 
     declaration-seqopt 

Sie können Namespace-Mitglieder außerhalb des Namensraum definieren, obwohl es muss wurden deklariert innerhalb der namespace (Hervorhebung von mir):

7.3.1.2 Namespace Mitglied Definitionen [namespace.memdef]

2 Mitglieder eines benannten Namespace können auch außerhalb dieses Namensraum durch explizite Qualifikation (3.4.3 definiert sein.2) des definierten Namens, vorausgesetzt, dass die zu definierende Entität bereits im Namespace deklariert wurde und die Definition nach dem Deklarationspunkt in einem Namespace erscheint, der den Namespace der Deklaration einschließt.

Wenn Sie

namespace name { 
    namespace space { 
     class ClassName; 
    } 
} 

schreiben Sie kein class ClassName in die namespace space erklärt, Sie bieten nur eine Vorwärtsdeklaration.

+1

Dies schließt nicht die Frage beantworten, die über die Angabe des Namespace in einer Klassendefinition ist. – interjay

+1

@interjay Ist es jetzt besser? –

+1

Ja, viel besser. Das OP sagt jedoch, dass er versucht hat, die Klasse im Namespace zu deklarieren, bevor sie definiert wurde, und es hat nicht funktioniert. – interjay

6

Nein, es funktioniert nicht. Ein Problem ist, dass mit

namespace name { 
    namespace space { 
     class ClassName { 
      // declarations 
     } 
    } 
} 

können Sie sagen, dass es zwei Namespaces und eine Klasse ist.

jedoch mit

class name::space::ClassName { 
    // declarations 
} 

kann man nicht sagen, ob space ein Namensraum oder eine Klasse ist ein verschachteltes ClassName enthält.

Was Sie können tun, ist auf Ihrer Registerkarte speichern. Es ist möglich zu schreiben

namespace name { namespace space { 
    class ClassName { 
     // declarations 
    } 
}} 
+0

Ah interessant, ich habe nicht über verschachtelte Klassen nachgedacht. Wie auch immer, wenn ich die Namespaces erkläre, sollte es nicht ambivalent sein, oder? Warum funktioniert es dann überhaupt nicht? (Siehe OP auf der Unterseite) – CharlyDelta

2

Was Sie suchen, funktioniert nicht.

Eine Erklärung ist, dass alle C++ class und struct Typen implizit mit einem eigenen Namespace verbunden sind (der den gleichen Namen wie die Klasse hat).

So gegeben

class name::space::ClassName 
{ 
// declarations 
}; 

der Compiler keine Möglichkeit hat, zu bestimmen, ob name und space sind tatsächlich Namespaces oder Klassen (im besten Fall, muss er feststellen, dass das Konstrukt nicht eindeutig ist). So muss der Compiler explizit gesagt, dass name ein Namespace ist, dass space ist ein Namensraum innerhalb name, bevor sie gesagt, dass ClassName ist eine Klasse in ihnen.

Daraus ergibt sich die Notwendigkeit für

namespace name 
{ 
    namespace space 
    { 
     class ClassName; 
    } 
} 

weiterleiten beide Namespaces angeben und nach vorne erklären ClassName in ihnen.

+0

Ja, ich verstehe jetzt das Problem, das auftaucht. Ich habe nicht darüber nachgedacht. Wenn ich jedoch die Namespaces nach vorn deklariere, sollte es nicht ambivalent sein, damit der Compiler dieses Problem lösen kann. – CharlyDelta

+1

Namespaces sind nicht "forward deklariert", Klassen und Strukturen sind. Aber um zu tun, was Sie wollen, wäre es notwendig, die Klassen innerhalb der Namespaces zu deklarieren, wie von Elephly gezeigt. – Peter

+0

Ich habe die falsche Terminologie im OP korrigiert, danke, dass Sie mich darauf aufmerksam gemacht haben. – CharlyDelta

Verwandte Themen