¿Por qué los objetos de la misma clase tienen acceso a los datos privados de los demás?

¿Por qué los objetos de la misma clase tienen acceso a los datos privados de los demás?

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 Es perfectamente posible que el objeto a tenga acceso a datos privados del objeto b y lo devuelva. ¿Por qué esto es así? Yo pensaría que los datos privados son privados. (Empecé tratando de entender los constructores de copia en el idioma pimpl, pero luego descubrí que ni siquiera entendía esta simple situación).

Porque así es como funciona en C ++. En C ++, el control de acceso funciona por clase , no por base de objeto.

El control de acceso en C ++ se implementa como una característica estática de tiempo de comstackción. Creo que es bastante obvio que no es posible implementar ningún control de acceso significativo por objeto en tiempo de comstackción. Solo el control por clase se puede implementar de esa manera.

Algunas sugerencias de control por objeto están presentes en la especificación de acceso protegido , por lo que incluso tiene su propio capítulo dedicado en el estándar (11.5). Pero aún así, todas las características por objeto descritas allí son bastante rudimentarias. Nuevamente, el control de acceso en C ++ está diseñado para funcionar en base a clases.

“Privado” no es realmente un mecanismo de control de acceso en el sentido de “Hice mis fotos en Facebook privadas para que no pueda verlas”.

En C ++, “privado” simplemente dice que estas son partes de una clase que usted (el codificador de la clase) podría cambiar en versiones futuras, etc., y no quiere que otros codificadores que usan su clase confíen en su existencia o funcionalidad. .

Si desea un verdadero control de acceso, debe implementar técnicas de seguridad de datos genuinas.

Esta es una buena pregunta y me he encontrado con esta pregunta recientemente. Tuve algunas discusiones con mis colegas y aquí está el resumen de nuestra discusión: Esto es por diseño. No significa que este diseño sea totalmente razonable para todos los casos, pero debe haber algunas consideraciones sobre por qué se elige una clase privada. Las posibles razones que podríamos pensar incluyen:

En primer lugar, el costo del control de acceso por instancia podría ser muy alto. Esto ha sido discutido por otros en este hilo. En teoría, esto se puede hacer a través de este control de puntero. Sin embargo, esto no se puede hacer en tiempo de comstackción, y solo se puede hacer en tiempo de ejecución. Por lo tanto, debe identificar el control de acceso de cada miembro en tiempo de ejecución, y cuando se infringe posiblemente solo se generarán excepciones. El costo es alto

En segundo lugar, el control de acceso por clase tiene su propio caso de uso, como copy constructor u operator =. Sería difícil implementarlos si el control de acceso es por instancia.

Además, el control de acceso es principalmente desde la perspectiva de progtwigción / lenguaje, de cómo modular / controlar el acceso al código / miembro, no a los datos.

Es algo así como una decisión de diseño de lenguaje arbitraria. En Ruby , por ejemplo, private realmente significa privado, como en “solo la instancia puede acceder a sus propios miembros de datos privados”. Sin embargo, esto es algo restrictivo.

Como se señaló en los comentarios, los constructores de copia y los operadores de asignación son lugares comunes donde accede directamente a los miembros de datos privados de otra instancia. Hay razones menos obvias por qué.

Considera el siguiente caso. Está implementando una lista enlazada OO. La lista enlazada tiene una clase de nodo nested para administrar punteros. Puede implementar esta clase de nodo de manera que administre los punteros en sí (en lugar de tener los punteros públicos y gestionados por la lista). En tal caso, tendría los objetos del nodo que desean modificar los punteros de otros objetos del nodo en otros lugares que el típico constructor de copia y el operador de asignación.

El truco es recordar que los datos son private para la clase , no la instancia de la clase. Cualquier método dentro de su clase puede acceder a los datos privados de cualquier instancia de esa clase; no hay una forma de mantener los datos privados en una instancia a menos que prohíba los métodos que acceden explícitamente a los miembros de datos privados de otras instancias.

Además de todas las respuestas anteriores, considere constructores de copia personalizada, operadores de asignación y todas las otras funciones que escribiría para una clase que opere en otras instancias . Necesitará funciones de acceso para todos los miembros de datos.

Los datos privados permanecen privados hasta que alguien que tiene acceso a ellos los revela a otros.

Este concepto se aplica a otras situaciones también, tales como:

 class cMyClass { public: // ... // omitted for clarity // ... void Withdraw(int iAmount) { iTheSecretVault -= iAmount; } private: int iTheSecretVault; }; 

¿Cómo podría alguien retirar el dinero? 🙂