De alguma forma, fiquei surpreso que o código a seguir seja compilado e executado (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;
}
É correto que esse código seja compilado corretamente? E por que isso está correto? Por que posso usar auto
em um tipo privado, enquanto não posso usar seu nome (conforme o esperado)?
c++
c++11
auto
private-members
hansmaad
fonte
fonte
f.Baz().i
também está OK, como estástd::cout << typeid(f.Baz()).name()
. O código fora da classe pode "ver" o tipo retornadoBaz()
se você puder se apossar dela, simplesmente não poderá nomeá-lo.private
existe uma conveniência para descrever APIs de uma maneira que o compilador possa ajudar a impor. Ele não tem como objetivo impedir o acesso ao tipoBar
pelos usuários deFoo
, portanto, não impede deFoo
forma alguma oferecer esse acesso retornando uma instância deBar
.#include <iostream>
. ;-)Respostas:
As regras para
auto
são, na maioria das vezes, as mesmas da dedução de tipo de modelo. O exemplo publicado funciona pelo mesmo motivo pelo qual você pode passar objetos de tipos privados para funções de modelo:E por que podemos passar objetos de tipos privados para funções de modelo, você pergunta? Porque apenas o nome do tipo está inacessível. O tipo em si ainda é utilizável, e é por isso que você pode devolvê-lo ao código do cliente.
fonte
public: typedef Bar return_type_from_Baz;
à classeFoo
na pergunta. Agora, o tipo pode ser identificado por um nome público, apesar de ser definido em uma seção privada da classe.private: typedef Bar return_type_from_Baz;
aFoo
, como demonstrado .typedef
Os identificadores não têm acesso a especificadores, públicos e privados.Bar
ouSomeDeducedType
? Não é como se eu pudesse usá-lo para acessar membros privadosclass Foo
ou algo assim.O controle de acesso é aplicado aos nomes . Compare com este exemplo do padrão:
fonte
Essa pergunta já foi respondida muito bem por Chill e R. Martinho Fernandes.
Eu simplesmente não podia deixar passar a oportunidade de responder uma pergunta com uma analogia de Harry Potter:
https://ideone.com/I5q7gw
Agradeço a Quentin por me lembrar da brecha de Harry.
fonte
friend class Harry;
faltando lá?friend class Dumbledore;
;);Wizard::LordVoldemort;
C ++ moderno. Em vez disso, ele ligausing Wizard::LordVoldemort;
. (Ele não se sente tão natural para usar Voldemort, honestamente ;-).Para adicionar aos outros (bom) respostas, aqui está um exemplo de C ++ 98 que ilustra que a questão realmente não tem a ver com
auto
nadaUsar o tipo privado não é proibido, ele estava apenas nomeando o tipo. Criar um temporário sem nome desse tipo é bom, por exemplo, em todas as versões do C ++.
fonte