Kürzlich sah ich ein seltsames C++-Feature: Klassenname eingefügt.
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 im alten C++ nicht existierte. Wann wurde es dann eingeführt? C++03? C++11?
Der eingefügte Klassenname bedeutet das X
wird als Mitglied erklärt X
also die Namenssuche im Inneren X
findet immer die aktuelle Klasse, keine andere X
die im selben umschließenden Geltungsbereich deklariert werden könnten, z
void X() { }
class X {
public:
static X create() { return X(); }
};
Ist der create()
Funktion zum Erstellen einer temporären X
Objekt oder Aufruf der Funktion X
? Auf Namensraumebene würde es die Funktion aufrufen, also besteht der Zweck des eingefügten Klassennamens darin, sicherzustellen, dass innerhalb des Hauptteils von X
der Name findet immer die Klasse selbst (weil die Namenssuche im eigenen Gültigkeitsbereich der Klasse beginnt, bevor sie im einschließenden Gültigkeitsbereich sucht).
Es ist auch innerhalb von Klassen-Templates hilfreich, wo der eingefügte Klassenname ohne eine Template-Argumentliste verwendet werden kann, zB using simply Foo
anstelle der vollständigen Template-ID Foo<blah, blah, blah>
, daher ist es einfach, auf die aktuelle Instanziierung zu verweisen. Sehen DR 176 für einen Wechsel zwischen C++98 und C++03, der das verdeutlichte.
Die Idee des eingefügten Klassennamens war in C++98 vorhanden, aber die Terminologie war neu für C++03.
C++98 sagt:
EIN Klassenname wird in den Gültigkeitsbereich eingefügt, in dem es unmittelbar nach deklariert ist Klassenname Wurde gesehen. Der Klassenname wird auch in den Gültigkeitsbereich der Klasse selbst eingefügt.
Der zweite Satz wurde um geändert DR 147 so sagt C++03 in [class]/2:
EIN Klassenname wird in den Gültigkeitsbereich eingefügt, in dem es unmittelbar nach deklariert ist Klassenname Wurde gesehen. Die Klassenname wird auch in den Geltungsbereich der Klasse selbst eingefügt; dies ist bekannt als die injizierter-Klassenname.
Schon vor C++98 hat der ARM einen ungefähr äquivalenten Wortlaut, was bedeutet, dass der Klassenname immer im Klassenrumpf verwendet werden kann, um auf die Klasse selbst zu verweisen:
Der Name einer Klasse kann als verwendet werden Klassenname sogar innerhalb der Mitgliederliste des Klassenbezeichners selbst.
- Zum Beispiel,
class link { link* next; };