2011-09-02 14 views
19

Intenté ajustar algo similar a los punteros de datos compartidos de Qt para mis propósitos, y al realizar las pruebas descubrí que cuando se llamaba a la función const, su versión no const era elegido en cambio.Llamar a una función const en lugar de a su versión no const

Estoy compilando con C++ 0x opciones, y aquí es un código mínimo:

struct Data { 
    int x() const { 
     return 1; 
    } 
}; 

template <class T> 
struct container 
{ 
    container() { 
     ptr = new T(); 
    } 


    T & operator*() { 
     puts("non const data ptr"); 
     return *ptr; 
    } 

    T * operator->() { 
     puts("non const data ptr"); 
     return ptr; 
    } 

    const T & operator*() const { 
     puts("const data ptr"); 
     return *ptr; 
    } 

    const T * operator->() const { 
     puts("const data ptr"); 
     return ptr; 
    } 

    T* ptr; 
}; 

typedef container<Data> testType; 

void testing() { 
    testType test; 
    test->x(); 
} 

Como se puede ver, Data.x es una función constante, por lo que el operador -> llamada debe ser el const uno. Y cuando comento el no-const, se compila sin errores, por lo que es posible. Sin embargo, mis impresiones de terminales:

"PTR datos const no"

¿Es un error GCC (tengo 4.5.2), o hay algo que me falta?

Respuesta

17

Si tiene dos sobrecargas que difieren solo en su const -ness, el compilador resuelve la llamada según si *this es const o no. En su código de ejemplo, test no es const, por lo que se invoca la sobrecarga no const.

Si hizo esto:

testType test; 
const testType &test2 = test; 
test2->x(); 

debería ver que el otro se llama a la sobrecarga, ya que es test2const.

+2

por lo que el compilador preferirá llamar a la sobrecarga sin const si el objeto no se declara const, incluso si pudiera llamar a la const overload? – coyotte508

+2

@ coyotte508: Precisamente. La sobrecarga sin '' contraste '' se considera una mejor coincidencia. –

1

Pero testType no es un objeto constante.

Por lo tanto, llamará a la versión no const de sus miembros.
Si los métodos tienen exactamente los mismos parámetros, tiene que elegir qué versión llamar (por lo que usa este parámetro (el oculto)). En este caso, esto no es const, así que obtienes el método no const.

testType const test2; 
test2->x(); // This will call the const version 

Esto no afecta a la llamada a x() como se puede llamar a un método en un objeto const no const.

2

No importa si Data::x es una función constante o no. El operador al que se llama pertenece a la clase container<Data> y no a la clase Data, y su instancia no es constante, por lo que se llama al operador no constante. Si solo había un operador constante disponible o la instancia de la clase era constante, se habría llamado al operador constante.

4

test es un objeto no const, por lo que el compilador encuentra la mejor coincidencia: la versión no const. Puede aplicar constness con static_cast sin embargo: static_cast<const testType&>(test)->x();

EDIT: Como acotación al margen, como usted sospechaba 99,9% de las veces se piensa que ha encontrado un error del compilador que debe revisar su código como es probable que haya algún capricho extraño y el compilador de hecho está siguiendo el estándar.

+0

+1 para el comentario "probablemente no has encontrado un error en el compilador" – MikMik

Cuestiones relacionadas