15 Stimmen

Warum können wir Namespace-Aliase nicht innerhalb einer Klasse deklarieren?

Es sieht so aus, als ob es unmöglich ist, einen Namespace-Alias innerhalb einer Klasse zu deklarieren; wir können dies jedoch auf Funktionsebene tun (getestet mit g++ 4.3.4):

namespace A
{
}

class C
{
  namespace N = A; // error: expected unqualified-id before `namespace'
};

class D
{
  void f();
};

void D::f()
{
  namespace N = A; // OK
}

Haben Sie eine Ahnung, warum eine solche Einschränkung besteht? Dies scheint nicht sehr konsistent mit typedefs zu sein, die innerhalb einer Klasse deklariert werden können.

6voto

UmmaGumma Punkte 5753

Gemäß C++ Standard 3.3.6

Die folgenden Regeln beschreiben den Geltungsbereich von in Klassen deklarierten Namen.

1) Der potentielle Geltungsbereich eines in einer Klasse deklarierten Namens besteht nicht nur aus dem deklarativen Bereich, der dem Deklarator des Namens folgt, sondern auch aus allen Funktionskörpern, Standardargumenten und Konstruktor-Ctor-Initialisierern in dieser Klasse (einschließlich solcher Dinge in verschachtelten Klassen). ...........

Sie können also nur Dinge aus dieser Liste im Klassenbereich deklarieren. Alles andere im Klassenbereich zu deklarieren ist ungültig. Nicht nur Namespace-Allianz, sondern auch Namespace. Zum Beispiel

class myClass
{
    //compilation error !!!
    namespace myNamespace
    {
    }
    using namespace std;//another compilation error
}

Editar:

Haben Sie eine Ahnung, warum eine solche Einschränkung besteht? Dies scheint nicht sehr konsistent mit typedefs zu sein, die innerhalb einer Klasse deklariert werden können.

Da die Verwendung von Typendefinitionen in Klassen sehr nützlich ist (zum Beispiel vector<int>::iterator ), während sie für Namespaces nutzlos ist. Betrachten Sie folgenden Code

class myClass
{
   namespce N=std;
};

//now let's use N
MyClass::N::vector<int> v;//don't you think, that this syntax is horrible, and useless?????

Zum Vergleich sehen Sie, was es in der Funktion

void f()
{
    namespace bnu= boost::numeric::ublas;
    bnu::matrix<int> m;//and now we can use short name bnu
}

Für die Klasse können wir den Namespace alliance in der cpp-Datei deklarieren und es gibt KEINE NOTWENDIGKEIT um sie in der Klassendeklaration zu vermerken.

5voto

Tony Punkte 9175

Ich bin zwar kein Experte für den C++-Standard, aber ich werde meinen Kopf hinhalten und versuchen, Ihre Frage zu beantworten. Ich nehme an, dass die Verwendung von namespace N = A innerhalb einer Klassendeklaration verstößt gegen die Definition, wie ein Klassenmitglied definiert werden sollte.

Der C++ Standard definiert ein Klassenmitglied als

member-specification:
  member-declaration member-specification_opt
  access-specifier : member-specification_opt
member-declaration:
  decl-specifier-seq_opt member-declarator-list_opt ;
  function-definition ;opt
  ::opt nested-name-specifier templateopt unqualified-id ;
  using-declaration
  static_assert-declaration
  template-declaration
member-declarator-list:
  member-declarator
  member-declarator-list , member-declarator
member-declarator:
  declarator pure-specifier_opt
  declarator constant-initializer_opt
  identifier_opt : constant-expression
pure-specifier:
  = 0
constant-initializer:
  = constant-expression

Der wichtigste Punkt ist die = in der Deklaration erwartet der Compiler entweder einen reinen Spezifizierer oder eine Konstanten-Initialisierungsanweisung, und da die Zeile nicht mit einer Null endet, wenden wir in diesem Fall keinen reinen Spezifizierer an.

Die Analyse der namespace N = A Deklaration sieht der Compiler dies als

declarator = constant-expression

Und da namespace ein Schlüsselwort ist, kann es nicht verwendet werden.

typedef ist erlaubt, weil (aus dem Standard)

Verschachtelte Typen sind Klassen und Aufzählungen, die in der Klasse definiert sind, und beliebige Typen, die mit Hilfe einer typedef-Deklaration als Mitglieder deklariert werden.

3voto

crmaunder Punkte 31

Ich bin nicht der Meinung, dass eine Namespace-Deklaration innerhalb einer Klasse völlig nutzlos ist. Es wäre nützlich, Aufzählungen innerhalb von Namespaces innerhalb von Klassen deklarieren zu können. Dies würde es Ihnen ermöglichen, auf die Elemente verschiedener Arrays mit logischen Indizes für das jeweilige Array zuzugreifen.

class myClass
{
   private:
        namespace TransAndRotIdx {
            enum { U, V, W, P, Q, R }; };
        namespace RotIdx {
            enum { P, Q, R }; };
        double tr[6];
        double r[3];

    public:
        double getTranslationMag(void)
        {
            using namespace TransAndRotIdx;
            return sqrt(tr[U]*tr[U]+tr[V]*tr[V]+tr[W]*tr[W]);
        }
        double getRotationMag(void)
        {
            using namespace RotIdx;
            return sqrt(tr[P]*tr[P]+tr[Q]*tr[Q]+tr[R]*tr[R]);
        }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X