¿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 acceda a datos privados del objeto by los devuelva. ¿Por qué esto es así? Creo que los datos privados son privados. (Comencé tratando de entender los constructores de copias en el idioma pimpl, pero luego descubrí que ni siquiera entendía esta simple situación).
c++
private-members
Keith
fuente
fuente
Respuestas:
Porque así es como funciona en C ++. En C ++, el control de acceso funciona por clase , no por objeto.
El control de acceso en C ++ se implementa como una característica estática en tiempo de compilación. Creo que es bastante obvio que no es realmente posible implementar ningún control de acceso significativo por objeto en tiempo de compilació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í, las características por objeto descritas allí son bastante rudimentarias. Nuevamente, el control de acceso en C ++ está diseñado para funcionar por clase.
fuente
void X::f(X&x)
, el compilador es fácilmente capaz de distinguirthis->a
yx.a
. No es (siempre) posible que el compilador sepa eso*this
y enx
realidad son el mismo objeto six.f(x)
se invoca, pero podría ver que un diseñador de lenguaje lo encuentra bien.this
y&x
son iguales. Para empeorar las cosas, esto acaba siendo un problema incluso conX::f(Y& y)
, porque nuestro objeto concreto podría ser de un tipoZ
que herede de ambosX
yY
. En resumen, es un verdadero desastre, no funciona, es difícil hacer que funcione con sensatez con MI.X::f(X& x)
, si hay accesos ax.a
, no compilaría. Nada más cambia, no es necesario insertar comprobaciones, por lo que el rendimiento de los programas aún válidos no se ve afectado. Y no se sugiere como un cambio radical en C ++ existente, sino como algo que los diseñadores podrían haber hecho al presentarloprivate
originalmente."Privado" no es realmente un mecanismo de control de acceso en el sentido de "Hice mis fotos en Facebook privadas para que no puedas 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 usen su clase dependan de su existencia o funcionalidad. .
Si desea un verdadero control de acceso, debe implementar técnicas de seguridad de datos genuinas.
fuente
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 por 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 esta verificación de puntero. Sin embargo, esto no se puede hacer en tiempo de compilación y solo se puede hacer en tiempo de ejecución. Por lo tanto, debe identificar el control de acceso de cada miembro en el 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 constructor de copias o operador =. Sería difícil implementarlos si el control de acceso es por instancia.
Además, el control de acceso es principalmente desde la perspectiva del lenguaje / programación, de cómo modularizar / controlar el acceso al código / miembro, no a los datos.
fuente
Es una decisión de diseño de lenguaje algo 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 se accede directamente a los miembros de datos privados de otra instancia. Hay razones menos obvias para ello.
Considere el siguiente caso. Está implementando una lista enlazada OO. La lista vinculada tiene una clase de nodo anidado para administrar punteros. Puede implementar esta clase de nodo de modo que administre los punteros en sí (en lugar de tener los punteros públicos y administrados por la lista). En tal caso, los objetos de nodo querrían modificar los punteros de otros objetos de nodo en otros lugares que el constructor de copia típico y el operador de asignación.
fuente
El truco consiste en recordar que los datos pertenecen
private
a la clase , no a 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 forma de mantener la privacidad de los datos dentro de una instancia a menos que prohíba los métodos que acceden explícitamente a los miembros de datos privados de otras instancias.fuente
Además de todas las respuestas anteriores, considere los constructores de copia personalizados, los operadores de asignación y todas las demás funciones que escribiría para una clase que opere en otras instancias . Necesitaría funciones de acceso para todos esos miembros de datos.
fuente
Los datos privados permanecen privados hasta que alguien que tenga acceso a ellos se los revele a otros.
Este concepto también se aplica a otras situaciones, como:
¿Cómo podría alguien retirar el dinero? :)
fuente