2010-07-04 19 views

Respuesta

1

Sí, es posible. Tendría que devolver el puntero (o referencia) desde el contexto de la clase, o alguien que tenga acceso a la clase friend. Esto se debe a que la variable en sí es privada y, por lo tanto, no se puede acceder de otra manera.

class C 
{ 
public: 
    int* getXPointer() 
    { 
     return &x; 
    } 

    int& getXReference() 
    { 
     return x; 
    } 

private: 
    int x; 
}; 


int main(int argc, char* argv[]) 
{ 
    C c; 
    int* p = c.getXPointer(); 
    int& r = c.getXReference(); 
    assert(p == &r); 
    return 0; 
} 
0

Sí, si entiendo bien, ¿le gustaría poder devolver un puntero a un miembro privado de una clase?

private: 
     int hidden; 
    public: 
     int& unHide() 
     { 
      return hidden; 
     } 
+0

¿Por qué ha especificado 'mutable'? –

+0

Mi mal, lo actualicé. – xil3

18

Sí, y de la misma manera crearía cualquier otro puntero. El truco es, por supuesto, que dado que el miembro es privado, solo puede crear el puntero dentro de la clase, donde puede ver el miembro.

class A 
{ 
    public: 
    int* getFooPtr() 
    { 
     return &foo; // OK; Inside the class foo is visible 
    } 

    private: 
    int foo; 
}; 

int main() 
{ 
    A a; 

    int* p_foo1 = &a.foo; // Illegal; Outside the class, foo is private 
    int* p_foo2 = a.getFooPtr(); // OK; getFooPtr() is a public member function 
} 

Por lo tanto, es posible crear punteros a los miembros privados, pero sólo dentro de las funciones miembro de la clase, y es posible devolver los punteros creados a partir de las funciones miembro. Si es una buena idea devolver punteros a miembros privados es otra pregunta por completo (generalmente no es una buena idea).

+1

Principalmente correcto, excepto para las funciones de miembros "solo dentro de la clase" ... '' friend's puede exponer elementos internos del objeto también :) –

+1

... así como el miembro estático se puede inicializar para señalar a un miembro privado de la clase , que no está dentro de ninguna función. – AnT

+0

Está hablando de un puntero al tipo de miembro, en mi opinión. – ThomasMcLeod

2

Sí, es posible, como las respuestas anteriores lo han demostrado. Pero cuando Tyler McHenry pregunta: "¿Es una buena idea?". No, no lo es. Las variables miembro se declaran privadas por una buena razón, y subvertir la encapsulación de esta manera solo dará lugar a problemas.

+3

Si es una buena idea, depende del escenario. Creo que la gente no estaría contenta si no pudieran obtener punteros en un estándar :: vector. –

+0

Hmm. Siempre pensé en los vectores como contenedores, pero tienes razón. –

+1

Declarar un puntero a un miembro privado no necesariamente subvierte la encapsulación. La única posibilidad de que se produzca alguna subversión es cuando el puntero es más accesible que el miembro. Nada en el OP sugiere que sea el caso. – AnT

1

La redacción de su pregunta es bastante confusa. Cuando alguien dice "declarar un puntero a algo", generalmente están hablando de los atributos relacionados con el tipo de un puntero, como en "declarar un puntero a int". La propiedad de ser privado no afecta en absoluto el tipo de miembro, lo que significa que un miembro del tipo int siempre es solo un miembro del tipo int, independientemente de si es público o privado. Esto significa inmediatamente que un puntero del tipo int * siempre se puede hacer para señalar a un miembro público del tipo int, oa un miembro privado del tipo int. No importa en absoluto si el miembro es público o privado.

Otra ambigüedad en la redacción es que en C++ hay punteros comunes (como int *) y hay punteros de tipo "puntero a miembro" (como int MyClass::*). Cuando dice "un puntero al miembro de datos de una clase", no está claro de qué tipo de puntero está hablando: ordinario o puntero-a-miembro. Sin embargo, lo anterior aún se aplica a ambos tipos: ambos pueden apuntar fácilmente a miembros públicos, protegidos o privados de la clase. Lo privado no hace diferencia.

Nuevamente, la propiedad de ser "privado" no afecta el tipo del miembro, solo afecta su accesibilidad cuando se lo refiere directamente, por su nombre. Entonces, para hacer que su puntero apunte a un miembro de datos privados de una clase, debe inicializar ese puntero (o asignarlo) en un área donde se puede acceder a ese miembro de datos privados: dentro de un método de la clase propietaria o dentro una función amiga

+1

Esto no es un respuesta, es un comentario. – ThomasMcLeod

+0

No es un comentario. Es una explicación completa de todas las interpretaciones posibles –

3

Puede acceder fuera de la clase declarante a cualquier miembro privado no estático si está explotando el hecho de que C++ le permite pasar la dirección del miembro privado en instanciación explícita. Sin embargo, no podrá acceder a miembros privados estáticos, ya que tiene que usar un puntero al miembro con esta técnica.

struct A 
{ 
    A() : x("proof!") {} 
private: 
    char const* x; 
}; 

template class stow_private<A_x,&A::x>; 

int main() 
{ 
     A a; 

     // Use the stowed private member pointer 
     std::cout << a.*stowed<A_x>::value << std::endl; 
}; 

Puede encontrar la aplicación de stowed<> y detalles aquí: http://bloglitb.blogspot.hu/2010/07/access-to-private-members-thats-easy.html y https://gist.github.com/dabrahams/1528856

Cuestiones relacionadas