Por que objetos da mesma classe têm acesso aos dados privados uns dos outros?
class TrivialClass {
public:
TrivialClass(const std::string& data) :
mData(data) {};
const std::string& getData(const TrivialClass& rhs) const {
return rhs.mData;
};
private:
std::string mData;
};
int main() {
TrivialClass a("fish");
TrivialClass b("heads");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
Este código funciona. É perfeitamente possível para o objeto a acessar dados privados do objeto be retorná-los. Por que deveria ser assim? Eu acho que os dados privados são privados. (Comecei tentando entender os construtores de cópia no idioma pimpl, mas depois descobri que nem mesmo entendia essa situação simples.)
c++
private-members
Keith
fonte
fonte
Respostas:
Porque é assim que funciona em C ++. Em C ++, o controle de acesso funciona por classe , não por objeto.
O controle de acesso em C ++ é implementado como um recurso estático de tempo de compilação. Acho que é bastante óbvio que não é realmente possível implementar qualquer controle de acesso por objeto significativo em tempo de compilação. Apenas o controle por classe pode ser implementado dessa forma.
Algumas dicas de controle por objeto estão presentes na especificação de acesso protegido , razão pela qual ela ainda tem seu próprio capítulo dedicado no padrão (11.5). Mas ainda assim, quaisquer características por objeto descritas lá são bastante rudimentares. Novamente, o controle de acesso em C ++ deve funcionar por classe.
fonte
void X::f(X&x)
, o compilador é facilmente capaz de distinguirthis->a
ex.a
. Nem (sempre) é possível para o compilador saber isso*this
e se elesx
são realmente o mesmo objeto sex.f(x)
for chamado, mas eu poderia muito bem ver um designer de linguagem achar isso OK.this
e&x
são os mesmos. Para piorar, isso acaba sendo um problema mesmo comX::f(Y& y)
, porque nosso objeto concreto pode ser do tipoZ
que herda deX
eY
. Resumindo, é uma verdadeira bagunça, sem desempenho, difícil de fazer com que o trabalho de IM seja sensato.X::f(X& x)
, se houver acesso ax.a
, ele não compilará. Nada mais muda, nenhuma verificação precisa ser inserida, então o desempenho de programas ainda válidos não é afetado. E não é sugerido como uma mudança significativa no C ++ existente, mas como algo que os designers poderiam ter feito na introduçãoprivate
original."Privado" não é realmente um mecanismo de controle de acesso no sentido de "Tornei minhas fotos privadas no Facebook para que você não possa vê-las".
Em C ++, "privado" simplesmente diz que essas são partes de uma classe que você (o codificador da classe) pode alterar em versões futuras, etc., e você não quer que outros programadores usando sua classe confiem em sua existência ou funcionalidade .
Se você deseja um controle de acesso verdadeiro, deve implementar técnicas genuínas de segurança de dados.
fonte
Esta é uma boa pergunta e eu encontrei essa pergunta recentemente. Tive algumas discussões com meus colegas e aqui está o resumo de nossa discussão: Isso ocorre por design. Isso não significa que esse design seja totalmente razoável para todos os casos, mas deve haver algumas considerações sobre o porquê de cada classe privada ser escolhida. Os possíveis motivos que podemos pensar incluem:
Em primeiro lugar, o custo do controle de acesso por instância pode ser muito alto. Isso foi discutido por outros neste tópico. Em teoria, isso pode ser feito por meio desta verificação de ponteiro. No entanto, isso não pode ser feito em tempo de compilação e só pode ser feito em tempo de execução. Portanto, você deve identificar o controle de acesso de cada membro em tempo de execução e, quando for violado, possivelmente apenas exceções serão levantadas. O custo é alto.
Em segundo lugar, o controle de acesso por classe tem seu próprio caso de uso, como construtor de cópia ou operador =. Seria difícil implementá-los se o controle de acesso fosse por instância.
Além disso, o controle de acesso é principalmente da perspectiva de programação / linguagem, para saber como modularizar / controlar o acesso ao código / membro, não aos dados.
fonte
É uma decisão arbitrária de design de linguagem. Em Ruby , por exemplo,
private
realmente significa privado, como em "apenas a instância pode acessar seus próprios membros de dados privados". No entanto, isso é um tanto restritivo.Conforme apontado nos comentários, os construtores de cópia e os operadores de atribuição são locais comuns onde você acessa os membros de dados privados de outra instância diretamente. Existem razões menos óbvias para isso.
Considere o seguinte caso. Você está implementando uma lista vinculada OO. A lista vinculada possui uma classe de nó aninhada para gerenciar ponteiros. Você pode implementar essa classe de nó de forma que ela gerencie os ponteiros em si (em vez de ter os ponteiros públicos e gerenciados pela lista). Nesse caso, você teria os objetos de nó desejando modificar os ponteiros de outros objetos de nó em outros lugares que o construtor de cópia típico e o operador de atribuição.
fonte
O truque é lembrar que os dados são
private
para a classe , não para a instância da classe. Qualquer método dentro de sua classe pode acessar os dados privados de qualquer instância dessa classe; não há uma maneira de manter os dados privados dentro de uma instância, a menos que você proíba os métodos que acessam explicitamente membros de dados privados de outras instâncias.fonte
Além de todas as respostas acima, considere construtores de cópia personalizados, operadores de atribuição e todas as outras funções que você escreveria para uma classe que operasse em outras instâncias . Você precisaria de funções de acessador para todos esses membros de dados.
fonte
Os dados privados permanecem privados até que alguém que tenha acesso a eles os revele a outra pessoa.
Este conceito também se aplica a outras situações, como:
Como alguém poderia sacar o dinheiro? :)
fonte