Ich war irgendwie überrascht, dass der folgende Code kompiliert und ausgeführt wird (vc2012 & gcc4.7.2)
class Foo {
struct Bar { int i; };
public:
Bar Baz() { return Bar(); }
};
int main() {
Foo f;
// Foo::Bar b = f.Baz(); // error
auto b = f.Baz(); // ok
std::cout << b.i;
}
Ist es richtig, dass dieser Code gut kompiliert wird? Und warum ist es richtig? Warum kann ich auto
einen privaten Typ verwenden, während ich seinen Namen nicht verwenden kann (wie erwartet)?
c++
c++11
auto
private-members
hansmaad
quelle
quelle
f.Baz().i
auch in Ordnung iststd::cout << typeid(f.Baz()).name()
. Code außerhalb der Klasse kann den zurückgegebenen Typ "sehen",Baz()
wenn Sie ihn erhalten können, können Sie ihn einfach nicht benennen.private
es eine Annehmlichkeit gibt, APIs so zu beschreiben, dass der Compiler sie durchsetzen kann. Es ist nicht beabsichtigt, den ZugriffBar
von Benutzern auf den Typ zu verhindernFoo
, daher wird esFoo
in keiner Weise daran gehindert, diesen Zugriff durch Rückgabe einer Instanz von anzubietenBar
.#include <iostream>
. ;-)Antworten:
Die Regeln für
auto
sind größtenteils dieselben wie für den Abzug von Vorlagentypen. Das veröffentlichte Beispiel funktioniert aus demselben Grund, aus dem Sie Objekte privaten Typs an Vorlagenfunktionen übergeben können:Und warum können wir Objekte privaten Typs an Vorlagenfunktionen übergeben, fragen Sie? Weil nur auf den Namen des Typs nicht zugegriffen werden kann. Der Typ selbst ist weiterhin verwendbar, weshalb Sie ihn überhaupt an den Clientcode zurückgeben können.
quelle
public: typedef Bar return_type_from_Baz;
der KlasseFoo
in der Frage hinzu. Jetzt kann der Typ durch einen öffentlichen Namen identifiziert werden, obwohl er in einem privaten Abschnitt der Klasse definiert ist.private: typedef Bar return_type_from_Baz;
zu gezeigtFoo
, wie gezeigt .typedef
Bezeichner haben keinen Zugriff auf öffentliche und private Bezeichner.Bar
oderSomeDeducedType
? Es ist nicht so, dass ich es benutzen kann, um zu privaten Mitgliedern vonclass Foo
oder irgendetwas zu gelangen.Die Zugriffskontrolle wird auf Namen angewendet . Vergleichen Sie mit diesem Beispiel aus dem Standard:
quelle
Diese Frage wurde sowohl von chill als auch von R. Martinho Fernandes bereits sehr gut beantwortet.
Ich konnte die Gelegenheit einfach nicht verpassen, eine Frage mit einer Harry-Potter-Analogie zu beantworten:
https://ideone.com/I5q7gw
Vielen Dank an Quentin, der mich an die Harry-Lücke erinnert hat.
quelle
friend class Harry;
?friend class Dumbledore;
Wizard::LordVoldemort;
modernes C ++ anruft . Stattdessen ruft er anusing Wizard::LordVoldemort;
. (Es fühlt sich nicht so natürlich an, Voldemort zu benutzen, ehrlich. ;-)So fügen Sie zu den anderen (gut) Antworten, hier ist ein Beispiel von C ++ 98 , die zeigt , dass das Problem wirklich nicht mit dem zu tun hat
auto
überhauptDie Verwendung des privaten Typs ist nicht verboten, es wurde nur der Typ benannt. Das Erstellen einer unbenannten temporären Datei dieses Typs ist beispielsweise in allen Versionen von C ++ in Ordnung.
quelle