programacion - herencia c++
Los especificadores de acceso no son infalibles (5)
Si tengo una clase como esta,
class Sample
{
private:
int X;
};
Entonces no podemos acceder a X desde afuera, así que esto es ilegal,
Sample s;
s.X = 10; // error - private access
¡Pero podemos hacer que sea accesible sin editar la clase ! Todo lo que tenemos que hacer es esto,
#define private public //note this define!
class Sample
{
private:
int X;
};
//outside code
Sample s;
s.X = 10; //no error!
Código de trabajo en ideone: http://www.ideone.com/FaGpZ
Eso significa que podemos cambiar los especificadores de acceso definiendo dichas macros justo antes de la definición de clase, o antes #include <headerfile.h>
,
#define public private //make public private
//or
#define protected private //make protected private
//or
#define so on
¿No es un problema con C ++ (Macros / especificadores de acceso / lo que sea)?
De todos modos, el objetivo de este tema es:
Al usar macros, podemos violar fácilmente la encapsulación. ¡Los especificadores de acceso no son infalibles! ¿Estoy en lo cierto?
¡Pero podemos hacer que sea accesible sin editar la clase! Todo lo que tenemos que hacer es esto,
Técnicamente, todo lo que has mostrado es que "podemos convertir un programa legal en Comportamiento no definido" sin editar una clase específica.
Eso no es noticia. También puede convertirlo en un comportamiento indefinido simplemente agregando una línea como esta al final de main()
:
int i = 0;
i = ++i;
Los especificadores de acceso en C ++ no son una característica de seguridad. No protegen contra los intentos de pirateo, y no protegen contra las personas que intencionalmente intentan introducir errores en su código.
Simplemente permiten que el compilador lo ayude a mantener ciertas invariantes de clase. Permiten que el compilador le informe si accidentalmente intenta acceder a un miembro privado como si fuera público. Todo lo que has mostrado es que "si trato de romper mi programa específicamente, puedo". Eso, afortunadamente, debería ser una sorpresa para absolutamente nadie.
Como dijo @Gman, la redefinición de palabras clave en el lenguaje C ++ es un comportamiento indefinido . Puede parecer que funciona en su compilador, pero ya no es un programa C ++ bien definido, y el compilador en principio podría hacer lo que quiera.
Pero podemos hacer que sea accesible sin editar la clase
No sin editar el archivo fuente que contiene la clase.
Sí, las macros te permiten dispararte en el pie. Esto no es una novedad ... pero este es un ejemplo particularmente no problemático, ya que para "violar la encapsulación" hay que forzar a la clase a definir la macro propiamente dicha o incluir un archivo de encabezado que lo haga.
Para decirlo de otra manera: ¿puedes ver que esto es un problema en el desarrollo de software real y responsable?
@Nawaz, tu publicación es interesante, nunca pensé en esto antes. Sin embargo, creo que la respuesta a su pregunta es simple: piense en C ++ (o probablemente en cualquier idioma) de seguridad como una forma de organizar su código, en lugar de una policía.
Básicamente, dado que todas las variables están definidas en su propio código, debería poder acceder a TODAS, sin importar dónde las defina. Por lo tanto, no debería sorprenderse que haya encontrado una forma de acceder a un miembro privado.
En realidad, incluso hay un método más fácil para acceder a variables privadas. Imagina que tienes una biblioteca con esta clase:
class VerySecure
{
private:
int WorldMostSecureCode;
};
Y digamos que estoy usando tu clase muy segura en mi código. Puedo acceder fácilmente al miembro privado de esta manera:
VerySecury a;
int *myhacker = (int*)(&a);
int b = (*myhacker);
printf("Here is your supposed world secret: %d :-) /n", b);
¡¡¿Como es eso?!!
En primer lugar, es ilegal hacer eso. private
es una palabra clave, y no se puede usar como un identificador en una macro; su programa estaría mal formado.
Pero en cualquier caso, no es un problema con las macros en absoluto. Es con el tonto que los usó de una manera tonta. :) (Están ahí para ayudarlo a estar seguro, no están ahí para ayudarlo a estar seguro y bloquear todo acceso a ellos sin importar lo que intente. C ++ protege contra Murphy, no contra Maquiavelo.)
Tenga en cuenta que puede acceder a partes privadas de una manera bien formada y bien definida, como se demuestra aquí . Nuevamente, esto no es un problema con el lenguaje, simplemente no es el trabajo del lenguaje hacer más de lo necesario para mantener las manos extendidas.
No. romperá el caos con métodos privados. si el compilador es capaz de decir que estos métodos privados no se pueden acceder a otra parte, se pueden alinear y optimizar, y es posible que no aparezcan en el archivo del objeto, por lo que serán inaccesibles.
Toma esto como un ejemplo. Funciona, no puede vincular o no puede ejecutar el ejecutable dependiendo de los indicadores de optimización / stripping que utiliza y cómo compila el objeto (es decir, puede poner la implementación en una biblioteca compartida o no)
class A {
// i need this one ...
private:
void stupid_private();
public:
void unlock(std::string password);
};
archivo de implementación:
#include <iostream>
#include "a.h++"
// uncomment this for more g++ fun
// __attribute__((visibility("hidden")))
void A::stupid_private() {
std::cout << "let''s output something silly." << std::endl;
}
void A::unlock(std::string password) {
if (password == "jumbo")
stupid_private();
}
el archivo de usuario:
#define private public
#include "a.h++"
int main() {
A a;
a.stupid_private();
return 0;
}