2010-02-08 25 views
9

¿Hay alguna forma de que pueda acceder a la variable de miembro privado de una clase?¿Hay alguna forma de que pueda acceder a la variable de miembro privado de una clase?

Edición: No desde una función miembro o función amiga sino a través de una instancia.

+0

Fue una entrevista de preguntas. No podía pensar en otra forma que no fuera hacer algún truco editable con la manipulación del puntero. Tomando la dirección del objeto, desplazamiento de la variable y luego imprímala ... Pero no estaba seguro de si el desplazamiento del varibale podría obtenerse correctamente. – Sandeep

+0

¿Quién es este empleador que le está pidiendo que abuse de su compilador? –

+0

La respuesta correcta es "do not". Podría declarar una clase de amigo para hacer esto, pero es un diseño bastante pobre para hacerlo. –

Respuesta

5

Simplemente echarlo, cambiar la memoria y devolver. (no compiló el código, pero debería tener la idea).

class Bla 
{ 
public: 
    Bla() : x(15), str("bla") {} 
private: 
    int x; 
    std::string str; 
} 

int main() 
{ 
    Bla bla; 

    int x = *((int*)(&bla)); 
    std::string str = *((std::string*)((int*)(&bla) + 1)); 

    std::cout << x << str; 

    return 0; 
} 

Dado que esta es una pregunta de la entrevista, no entraré en por qué no debes hacer eso. :)

EDITAR: Las clases con funciones virtuales también tendrán un puntero de tabla virtual en alguna parte. No estoy seguro si & le dará la dirección de vt o la dirección del primer miembro de datos.

La alineación es 4 por defecto (¿no?), Por lo que si el miembro que está leyendo no se alinea, cambie 2 bytes para pasar al siguiente.

+0

Podría no funcionar si la clase tiene funciones virtuales. –

+0

Es posible que un optimizador reorganice el orden de asignación de los miembros privados, por lo que no se garantiza que funcione. –

+0

El destino del puntero de tabla virtual depende de la implementación (el estándar ni siquiera requiere que exista uno, aunque todos lo hacen), y si hay miembros públicos o protegidos, el compilador puede interferir hasta cierto punto con el orden de las variables. –

0

Sí, por qué no, a través de una función miembro

5

Uno de los "trucos sucios" de C++ es hacer algo como:

#define private public 
#include "ClassHeader.h" 

// now all the private members of the included class are public 

I fuertemente No recomiendo que lo haga.

+0

jajajajaja eso es oro –

+4

Aunque hayas agregado el descargo de responsabilidad, algunas cosas simplemente no deberían ser entregadas ... hace que sea muy fácil para los locos hacerlo. –

+7

Sección 17.4.3.1.1 del Estándar C++: "Tampoco dicha unidad de traducción definirá macros para nombres léxicamente idénticos a palabras clave". Por supuesto, ningún compilador conocido rechaza tales programas. –

5

Se podía:

  1. Coloque los miembros privados en la sección pública
  2. Hacer funcionar su clase o un amigo de la clase.
  3. Proporcione un descriptor de acceso a los datos.
  4. Tome la dirección de la clase, agregue el desplazamiento a esa variable, molde y desreferencia. (Yuck)

¿Qué estás tratando de hacer? Si algo es privado, no te metas con eso. Es privado por una razón.

+0

En mi humilde opinión, el cuarto es el mejor :) – akif

+0

Recordé esta historia mientras leía su respuesta https://en.wikipedia.org/wiki/Barometer_question –

3

Sí. Puede acceder a un miembro privado:

  • ... en otras instancias del mismo tipo (exacto).
  • ... dentro de clases o funciones declaradas como amigo de esa clase.
  • ... a través de una función de miembro de acceso público (getter/setter).
2

Si bien estamos proponiendo malas ideas, no hay nada en el código que impone la encapsulación, es un truco de compilación por completo, por lo que puede escribir el ensamblado para acceder directamente a miembros privados.

Pero ¿por qué no reescribir la clase base si no está haciendo lo que ya quiere?

2

¿Por qué le gustaría?

reglas de visibilidad son claras:

  • métodos privados han de ser visitada únicamente por los métodos de la clase
  • métodos protegidas pueden ser accedidos por los métodos de la clase o descendientes
  • métodos públicos se puede acceder por cualquiera

... por lo tanto, si escribe la clase usted mismo, elija la visibilidad correcta. Si se trata de una clase suministrada, cosa cuidadosamente por qué se hizo privada en primer lugar ...

Si decide romper esa regla, sin embargo, tiene varias opciones:

  • puede hacerse amigo de la clase que debe tener acceso a los métodos privados a través de un especificador
  • friend puede utilizar un truco preprocesador fea que probablemente alguien ya haya publicado, pero hazlo solo si necesitas usar los campos o métodos para hacer pruebas unitarias - cualquier otro uso es un mal diseño
  • puedes usar un feo hack de tipografía, pero es tan feo que me da miedo incluso publicarlo no a obtener downvoted;>
+2

Anónimo cobarde down-voting? –

+0

Probablemente el OP. Parece que rechaza todas las respuestas correctas: "no". – GManNickG

12

GotW #76 tiene fascinantes detalles de lenguaje y jurisprudencia sobre cómo hacer algunas de estas cosas. :-)

+1

Ese truco de plantilla es increíble, pero necesita que la clase tenga algo en plantilla. – Eugene

+0

@Chris, ehh, no puedo superarlo si hace referencia a GotW:> –

+0

Mi preferencia va al macro truco, tan fácil ... –

0

Creo que depende de cómo se formula la pregunta:

Q: ¿Cómo acceder a una variable miembro privada? A: No lo haría.

Junto con:

Q: ¿Cómo poner en práctica ... R: Me gustaría no, es ya está hecho, me gustaría aprovechar un marco/biblioteca existente.

Los entrevistadores no siempre quieren saber si usted puede hacer una rueda, a veces están sondeando para ver si sabe cómo encontrar la estación de servicio más cercana. :)

Cuestiones relacionadas