Warum gibt es einen injizierten Klassennamen?

147

Kürzlich habe ich eine seltsame C ++ - Funktion gesehen: injizierter Klassenname .

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

Aber ich kann nicht herausfinden, warum diese Funktion notwendig ist. Gibt es eine Praxis, die diese Funktion erfordert?

Und ich habe gehört, dass diese Funktion in altem C ++ nicht existiert. Wann wurde es dann eingeführt? C ++ 03? C ++ 11?

ikh
quelle
Buddy, kannst du auf Skype schauen? Ich kann dich nicht erreichen
Irinel Iovan

Antworten:

162

Der injizierte Klassenname bedeutet, dass er Xals Mitglied von deklariert ist X, sodass bei der Namenssuche im Inneren Ximmer die aktuelle Klasse gefunden wird, nicht eine andere X, die möglicherweise im selben umschließenden Bereich deklariert wird, z

void X() { }
class X {
public:
  static X create() { return X(); }
};

Erstellt die create()Funktion ein temporäres XObjekt oder ruft sie die Funktion auf X? Im Namespace-Bereich würde es die Funktion aufrufen. Der Zweck des injizierten Klassennamens besteht also darin, sicherzustellen, dass innerhalb des Hauptteils des XNamens immer die Klasse selbst gefunden wird (da die Namenssuche im eigenen Bereich der Klasse beginnt, bevor sie in das Gehäuse schaut Umfang).

Dies ist auch in Klassenvorlagen hilfreich, in denen der Name der injizierten Klasse ohne eine Liste mit Vorlagenargumenten verwendet werden kann, z. B. einfach Fooanstelle der vollständigen Vorlagen-ID Foo<blah, blah, blah>, sodass Sie leicht auf die aktuelle Instanziierung verweisen können. Siehe DR 176 für eine Änderung zwischen C ++ 98 und C ++ 03, die dies verdeutlichte.

Die Idee des injizierten Klassennamens war in C ++ 98 vorhanden, aber die Terminologie war neu für C ++ 03.

C ++ 98 sagt:

Ein Klassenname wird in den Bereich eingefügt, in dem er unmittelbar nach dem Anzeigen des Klassennamens deklariert wird. Der Klassenname wird auch in den Bereich der Klasse selbst eingefügt.

Der zweite Satz wurde von DR 147 geändert, so dass C ++ 03 in [Klasse] / 2 sagt:

Ein Klassenname wird in den Bereich eingefügt, in dem er unmittelbar nach dem Anzeigen des Klassennamens deklariert wird. Der Klassenname wird auch in den Bereich der Klasse selbst eingefügt. Dies ist als Name der injizierten Klasse bekannt .

Noch vor C ++ 98 hat der ARM einen ungefähr äquivalenten Wortlaut, was bedeutet, dass der Klassenname immer im Klassenkörper verwendet werden kann, um auf die Klasse selbst zu verweisen:

Der Name einer Klasse kann als verwendet werden class-name auch innerhalb der Mitgliedsliste der Klasse specifier selbst.

  • Beispielsweise,

    class link { link* next; };

Jonathan Wakely
quelle
2
Das wurde ich ziemlich oft gefragt, konnte aber nie ein einfaches Beispiel für das Problem finden. Also +1 Für das Beispiel.
Dhein
1
Dies ist deutlich zu sehen, wenn Sie clang ++ your_program.cpp -Xclang -ast-dump ausführen und Ihre Klasse und dann einen injizierten untergeordneten Klassenknoten sehen.
Xaxxon