Nos bastidores do público, privado e protegido

Dec 08 2020

Tento mergulhar mais fundo e entender as diferenças entre Público | Privado | Protegido em uma perspectiva de baixo nível, em C ++.

Como são as diferenças entre os três expressas na memória?

Respostas

5 largest_prime_is_463035818 Dec 08 2020 at 20:48

private, publicE protectednão causa membros para ser armazenado em regiões específicas de memória. O acesso é verificado pelo compilador. No nível mais baixo, não há diferença.

No entanto, os especificadores de acesso têm efeito sobre as garantias que você obtém na ordem em que os membros da classe são dispostos na memória.

Do rascunho padrão do C ++ 17 :

Membros de dados não estáticos de uma classe (não-união) com o mesmo controle de acesso (Cláusula [class.access]) são alocados para que os membros posteriores tenham endereços mais altos dentro de um objeto de classe. A ordem de alocação de membros de dados não estáticos com controle de acesso diferente não é especificada (Cláusula [acesso à classe]). Os requisitos de alinhamento de implementação podem fazer com que dois membros adjacentes não sejam alocados imediatamente um após o outro; o mesmo pode acontecer com os requisitos de espaço para gerenciar funções virtuais ([class.virtual]) e classes básicas virtuais ([class.mi]).

Isso significa que para

 struct foo {
     private:
        int x;
     protected:
        int a;
        int b;
     public:
        int m;
        int n;
     private:
        int y;
};

Você só tem a garantia de que na memória xvem antes y, avem antes be mvem antes n. Fora isso, a ordem em que os membros são dispostos na memória não é especificada.

No entanto, raramente a ordem dos membros na memória é uma informação útil. Portanto, não é muito errado dizer que os especificadores de acesso não têm nada a ver com "memória de baixo nível".

2 SergeBallesta Dec 08 2020 at 20:44

No nível mais baixo (representação de bytes de objetos), não há absolutamente nenhuma diferença entre público, privado e protegido. No máximo, os compiladores podem (mas não são obrigados a) reordenar os membros de acordo com sua visibilidade.

No nível intermediário (comportamento em tempo de execução), há pouca ou nenhuma diferença. Se você encontrar um ponteiro público para dados privados, poderá usá-lo com segurança. Especificamente, isso é diferente de constness onde usar um ponteiro não const para alterar dados const é explicitamente um comportamento indefinido e pode causar erros SIGSEGV.

A diferença está apenas no nível mais alto. Você pode usar membros públicos de qualquer lugar, enquanto membros privados só podem ser usados ​​na classe onde são declarados e os membros protegidos podem ser usados ​​de sua classe e todas as classes que os herdam - mas a amizade pode permitir que classes específicas de função tenham acesso privado ou protegido dados.

Yunnosch Dec 08 2020 at 20:35

De modo nenhum.

O acesso é "concedido / negado" pelo compilador.

Qualquer acesso que não corresponda a uma visibilidade apropriada (conforme controlado pela classe do objeto acessado, via ponteiro ou não) é impedido antes da construção.

Nota:

As outras respostas discutem proveitosamente o efeito da visibilidade na ordem na memória.

No entanto, respondi a uma pergunta diferente que li na postagem do OPs "Como os recursos de proteção de memória são usados ​​para implementar a acessibilidade / visibilidade do membro?", Que em relação a causa e efeito é a pergunta inversa. Ou apenas a ordenação / estruturação dos membros em memórias configuradas de forma diferente é a ferramenta para alcançar o efeito de visibilidade desejado, o que por sua vez exigiria (mas não faria) os membros serem ordenados de uma determinada maneira.

Ou seja, não vejo um conflito entre as respostas, apenas uma interpretação diferente da pergunta.