Byłem w jakiś sposób zaskoczony, że poniższy kod kompiluje się i działa (vc2012 i 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;
}
Czy to prawda, że ten kod kompiluje się dobrze? A dlaczego to prawda? Dlaczego mogę używać auto
na typie prywatnym, podczas gdy nie mogę używać jego nazwy (zgodnie z oczekiwaniami)?
c++
c++11
auto
private-members
hansmaad
źródło
źródło
f.Baz().i
to również jest w porządku, tak jak jeststd::cout << typeid(f.Baz()).name()
. Kod poza klasą „widzi” zwracany typ,Baz()
jeśli możesz go zdobyć, po prostu nie możesz go nazwać.private
jest to wygoda opisywania interfejsów API w sposób, który kompilator może pomóc w egzekwowaniu. Nie ma to na celu uniemożliwienia dostępu do typuBar
przez użytkownikówFoo
, więc nie utrudniaFoo
w żaden sposób oferowania tego dostępu przez zwrócenie wystąpieniaBar
.#include <iostream>
. ;-)Odpowiedzi:
Zasady dotyczące
auto
są w większości takie same, jak w przypadku odliczenia typu szablonu. Opublikowany przykład działa z tego samego powodu, dla którego możesz przekazywać obiekty typu prywatnego do funkcji szablonu:Pytasz, dlaczego możemy przekazywać obiekty typu prywatnego do funkcji szablonu? Ponieważ niedostępna jest tylko nazwa typu. Sam typ jest nadal użyteczny, dlatego w ogóle można go zwrócić do kodu klienta.
źródło
public: typedef Bar return_type_from_Baz;
do klasyFoo
w pytaniu. Teraz typ można zidentyfikować za pomocą nazwy publicznej, mimo że został zdefiniowany w prywatnej sekcji klasy.private: typedef Bar return_type_from_Baz;
doFoo
, jak pokazano .typedef
Identyfikatory nie są świadome dostępu do specyfikatorów, publicznych i prywatnych.Bar
czySomeDeducedType
? To nie tak, że mogę go użyć, żeby dostać się do prywatnych członkówclass Foo
czy czegokolwiek.Kontrola dostępu jest stosowana do nazw . Porównaj z tym przykładem ze standardu:
źródło
Na to pytanie bardzo dobrze odpowiedział już zarówno chill, jak i R. Martinho Fernandes.
Po prostu nie mogłem przegapić okazji, aby odpowiedzieć na pytanie analogią do Harry'ego Pottera:
https://ideone.com/I5q7gw
Dziękuję Quentinowi za przypomnienie mi luki w Harrym.
źródło
friend class Harry;
brakuje?friend class Dumbledore;
;)Wizard::LordVoldemort;
nowoczesnego C ++. Zamiast tego dzwoniusing Wizard::LordVoldemort;
. (Szczerze mówiąc, używanie Voldemorta nie jest takie naturalne. ;-)Aby dodać do innych (dobrze) odpowiedzi, oto przykład z C ++ 98, która pokazuje, że problem naprawdę nie mają do czynienia z
auto
wcaleUżywanie typu prywatnego nie jest zabronione, było tylko nadaniem mu nazwy. Utworzenie nienazwanego tymczasowego typu tego typu jest w porządku, na przykład we wszystkich wersjach C ++.
źródło