2012-02-25 15 views
11

Estoy confundido por esta situación y Google no me dio la respuesta. Básicamente tengo el siguiente código simple que no se compila:llamada ambigua a la función estática sobrecargada

#include <iostream> 

class A 
{ 
public: 
    int a(int c = 0) { return 1; } 
    static int a() { return 2; } 
}; 

int main() 
{ 
    std::cout << A::a() << std::endl; 
    return 0; 
} 

En la elaboración de este, GCC 4.2 dice que la llamada a A::a() en main() es ambigua con las dos versiones de a() candidatos válidos. El compilador LLVM 3.0 de Apple compila sin error.

¿Por qué gcc está confundido acerca de qué función quiero llamar? Pensé que era obvio que calificando a() con A:: estoy pidiendo la versión static de la función. Naturalmente, este código aún no se compila si elimino la función statica(), porque A::a() no es una sintaxis válida para llamar al statica().

¡Gracias por cualquier comentario!

+0

BTW, búsqueda de Google rápida por mí: "Resolución de nombre de funciones de miembro estáticas y no estáticas C++" surgió con otra pregunta de SO: http: //stackoverflow.com/questions/5365689/c-overload-static-function -with-no-static-function – Bingo

+0

oops mi google-fu me ha fallado ... – fang

Respuesta

6

El motivo es que C++ especifica que esto es ambiguo. La resolución de sobrecarga especifica que para A::a, dado que this no está dentro del alcance, la lista de argumentos en esa llamada se ve aumentada por un argumento de objeto A ideado, en lugar de *this. resolución de sobrecarga no excluye funciones miembro no estáticas, sino que

Si la lista de argumentos se ve aumentada por un objeto artificial y la resolución de la sobrecarga selecciona una de las funciones miembro no estáticos de T, la llamada está mal formada, .

Esto ha sido recientemente objeto de una amplia discusión tanto en el comité en el contexto de core issue 1005. Consulte core issue 364 que consideró cambiar esta regla pero no lo hizo.

+0

Gracias por la referencia. Sin embargo, todavía estoy luchando por comprender por qué "la resolución de sobrecarga selecciona una de las funciones miembro no estáticas de T". Si entiendo lo que dijiste correcto, el a() no estático tiene dos argumentos: esto y un argumento con valor predeterminado (c = 0). El estático a() tiene un "argumento de objeto A artificial". Como no estoy suministrando un puntero "this" en la llamada, ¿por qué se seleccionaría la versión no estática? – fang

+0

No, 'this' no es un argumento en esta llamada porque no hay' este 'en el alcance. Esa es la razón por la que pasamos un "argumento de objeto A artificial" en nuestro llamado. Ambas funciones tienen un parámetro de objeto implícito (para las funciones estáticas, ese parámetro se usa solo para recibir el argumento de objeto A ideado). El parámetro de objeto implícito del 'a' no estático tiene el tipo' A & 'en su caso (' A const & 'en el miembro const fncs). El argumento del objeto ideado en la llamada 'A :: a()' coincide con ambos parámetros de objetos implícitos, por lo que tiene una ambigüedad. –

+0

¿Entonces este "argumento de objeto A artificial" es del mismo tipo que * esto? – fang

3

La razón es que la resolución del nombre ocurre antes que cualquier otra cosa que haga el compilador, como averiguar qué función sobrecargada usar.

Al calificar la función con A::, simplemente le dice al compilador que "busque dentro de A para encontrar el nombre a". En realidad, no ayuda a resolver a qué función te refieres.

EDITAR

Y así, cuando se escribe A::a(), primero el compilador piensa "mirar en A para una función miembro o miembro que puede utilizar operator()".

A continuación, el compilador piensa: "Ok, dos posibilidades aquí, que uno se está refiriendo? a() o a(int c = 0) con un defecto c=0. No estoy seguro.

Si ha retirado la palabra clave estática y llama a las funciones como obj.a() , todavía habría una ambigüedad.

WRT analizador de LLVM

diría que lo hace un poco de trabajo extra para usted, que no es requerido por la norma, lo que sería asumir A::a() es estático.

+0

¿Alguien me puede responder, significa eso para las funciones 'estáticas', la definición' estática' forma parte del nombre de manipulación, para propósitos de resolución? – Bingo

+0

No lo sé. Pero el cambio de nombre es un problema de enlazador, no un problema de compilación. –

+0

¿Alguna idea de por qué la LLVM de Apple lo compila bien? ¿Eso significa que el analizador de LLVM nombra la resolución en algún otro orden? – fang

Cuestiones relacionadas