2009-07-29 19 views
14

Estoy tratando de crear una clase con dos métodos con el mismo nombre, utilizado para acceder a un miembro privado. Un método es público y const calificado, el otro es privado y no const (utilizado por una clase de amigo para modificar el miembro a modo de retorno por referencia).privado no const y función de miembro público - ¿coexistir en paz?

Desafortunadamente, recibo errores de compilación (usando g ++ 4.3): Cuando utilizo un objeto no const para llamar al método, g ++ se queja de que la versión no const de mi método es privada, aunque sea pública (const) la versión existe

Esto parece extraño, porque si la versión privada no const no existe, todo compila bien.

¿Hay alguna manera de que esto funcione? ¿Se compila en otros compiladores?

Gracias.

Ejemplo:

class A 
{ 
public: 
    A(int a = 0) : a_(a) {} 
public: 
    int a() const { return a_; } 
private: 
    int & a()  { return a_; } /* Comment this out, everything works fine */ 
    friend class B; 
private: 
    int a_; 
}; 


int main() 
{ 
    A  a1; 
    A const a2; 

    cout << a1.a() << endl; /* not fine: tries to use the non-const (private) version of a() and fails */ 
    cout << a2.a() << endl; /* fine: uses the const version of a() */ 
} 
+0

¿Por qué este fracaso? C++ permite la conversión de non-const a const, vis a vis parámetro de función. – jkeys

Respuesta

13

resolución de sobrecarga ocurre antes de la comprobación de acceso, por lo que cuando se llama al método en un no constante A, el miembro no const es elegida como una mejor adaptación. El compilador falla luego debido a la verificación de acceso.

No hay forma de "hacer que esto funcione", mi recomendación sería cambiar el nombre de la función privada. ¿Hay alguna necesidad de tener un acceso privado?

+0

Una clase oculta sería mi mejor opción, como usar una estructura Node dentro de una clase más grande. – jkeys

+0

Eso es muy malo. Sospeché que este sería el caso, pero no veo por qué tiene que ser así. Espero que alguien me muestre por qué tiene que ser así, así que puedo descansar fácilmente. La razón por la que deseo este comportamiento es porque generalmente escribo mis getters y setters como dos versiones const/non-const del mismo método, sin el prefijo "get"/"set". Para esta clase en particular, no quiero permitir que ninguna clase excepto una use los setters (de ahí la declaración de clase friend). – mmocny

+0

La capacidad de sobrecargar la función es principalmente útil cuando las funciones realizan la misma operación lógica, o similar, pero en un tipo diferente de argumento (especialmente útil para escribir código genérico en plantillas). Recuperar el valor de algo es una operación diferente de obtener una referencia a algo para actualizarlo. Por esta razón, tiene sentido (¡al menos para mí!) Dar diferentes nombres a las funciones. Creo que estás 'nadando contra la corriente' si tratas de mantener los mismos nombres. –

2

Sólo se seleccionará la versión const si el objeto está declarada es const, de lo contrario, seleccionar la versión no const (incluso si eso se traduce en un error).

Esto debería funcionar:

cout << ((const A*)&a1)->a() << endl; 

o esto:

A const& ra1 = a1; 
cout << ra1.a() << endl; 
+1

Creo que preferiría 'const_cast (a1) .a()'. Parecería un poco más seguro. –

+0

Sí, ese es el mejor La forma de hacerlo es utilizar un yeso. No creo que sea más seguro que el segundo método, sin embargo, el compilador aplicará la seguridad de tipo completo para la asignación a la referencia. De todos modos, pensé que implementaría esto al, por ejemplo, cambiar las firmas de métodos de 'A &' a 'A const &' cuando estás pasando estas cosas, en lugar de manipularlas directamente como en este ejemplo obviamente artificial. –

+1

No entiendo por qué la respuesta de Charles Bailey tiene una votación más alta que esta respuesta (en mi humilde opinión correcta y en funcionamiento) de Tim Sylvester, que muestra lo contrario de _No hay forma de "hacer que esto funcione" _. En realidad, vine aquí porque sabía que era así Hice este tipo de problemas en algún lugar de mi código, pero olvidé dónde y cómo. (Por cierto, lo resolví exactamente como se describe arriba. Puede ser, debería intentar buscar en mi propio código fuente local la próxima vez ...) – Scheff

Cuestiones relacionadas