una teorico programas programa privada practico polimorfismo herencia for ejemplos ejemplo constructores completo autos agencia c++ c++11 auto private-members

teorico - polimorfismo en c++



¿Por qué puedo usar auto en un tipo privado? (4)

El control de acceso se aplica a los nombres . Compare con este ejemplo del estándar:

class A { class B { }; public: typedef B BB; }; void f() { A::BB x; // OK, typedef name A::BB is public A::B y; // access error, A::B is private }

De alguna manera me sorprendió que el siguiente código compila y ejecuta (vc2012 y 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; }

¿Es correcto que este código compila bien? ¿Y por qué es correcto? ¿Por qué puedo usar auto en un tipo privado, mientras que no puedo usar su nombre (como se esperaba)?


Esta pregunta ya ha sido respondida muy bien tanto por chill como por R. Martinho Fernandes.

Simplemente no podía dejar pasar la oportunidad de responder una pregunta con una analogía de Harry Potter:

class Wizard { private: class LordVoldemort { void avada_kedavra() { // scary stuff } }; public: using HeWhoMustNotBeNamed = LordVoldemort; }; int main() { Wizard::HeWhoMustNotBeNamed tom; // OK Wizard::LordVoldemort not_allowed; // Not OK return 0; }


Las reglas para auto son, en su mayor parte, las mismas que para la deducción de tipo de plantilla. El ejemplo publicado funciona por la misma razón por la que puede pasar objetos de tipos privados a funciones de plantilla:

template <typename T> void fun(T t) {} int main() { Foo f; fun(f.Baz()); // ok }

¿Y por qué podemos pasar objetos de tipos privados a funciones de plantillas? Porque solo el nombre del tipo es inaccesible. El tipo en sí todavía se puede usar, por lo que puede devolverlo al código del cliente.


Para agregar a las otras (buenas) respuestas, aquí hay un ejemplo de C ++ 98 que ilustra que el problema realmente no tiene que ver con el auto en absoluto

class Foo { struct Bar { int i; }; public: Bar Baz() { return Bar(); } void Qaz(Bar) {} }; int main() { Foo f; f.Qaz(f.Baz()); // Ok // Foo::Bar x = f.Baz(); // f.Qaz(x); // Error: error: ‘struct Foo::Bar’ is private }

Usar el tipo privado no está prohibido, solo estaba nombrando el tipo. Crear un temporal sin nombre de ese tipo está bien, por ejemplo, en todas las versiones de C ++.