2011-01-12 13 views
16

¿Qué significa este mensaje de error?La llamada de la función sobrecargada es ambigua

error: call of overloaded ‘setval(int)’ is ambiguous 
huge.cpp:18: note: candidates are: void huge::setval(unsigned int) 
huge.cpp:28: note:     void huge::setval(const char*) 

Mi código es el siguiente:

#include <iostream> 
#define BYTES 8 
using namespace std ; 

class huge { 
private: 
    unsigned char data[BYTES]; 
public: 
    void setval(unsigned int); 
    void setval(const char *); 
}; 

void huge::setval(unsigned int t) { 
    for(int i = 0; i< BYTES ; i++) { 
     data[i] = t; 
     t = t >> 1; 
    } 
} 

void huge::setval(const char *s) { 
    for(int i = 0; i< BYTES ; i++) 
     data[i] = s[i]; 
} 

int main() { 
    huge p; 
    p.setval(0); 
    return 0; 
} 
+4

Supongo que la respuesta a esta pregunta dependerá de la versión de la función a la que intente llamar. Podría suponer, pero claramente no puedo estar seguro de ninguna manera a menos que me lo diga. ¿Funcionaría eso con el compilador? Me pregunto ... –

+0

@KonradRudolph El literal '0' es un valor válido para' unsigned int' y 'const char *'. –

+0

@RyanP Sí, en general soy consciente. No tengo idea de lo que quería decir en ese entonces. –

Respuesta

17

El literal 0 tiene dos significados en C++.
Por un lado, es un número entero con el valor 0.
Por otro lado, es una constante de puntero nulo.

Como su función setval puede aceptar int o char*, el compilador no puede decidir qué sobrecarga quiere decir.

La solución más fácil es simplemente lanzar el 0 al tipo correcto.
Otra opción es para asegurar que se prefiere la sobrecarga int, por ejemplo, haciendo el otro una plantilla:

class huge 
{ 
private: 
    unsigned char data[BYTES]; 
public: 
    void setval(unsigned int); 
    template <class T> void setval(const T *); // not implemented 
    template <> void setval(const char*); 
}; 
+0

Por lo que vale, tuve que incluir la especialización fuera de la declaración de clase. Básicamente, incluye 'template <> void huge :: setval (const char *);' justo debajo de tu declaración de clase. Si no lo hice, recibí un error sobre la especialización de la plantilla en el alcance de la clase. Sin embargo, un gran truco, esto me ha impresionado antes con algunas de mis interfaces. – vmrob

+1

'0' tiene solo un significado en C++. Es un literal entero del tipo 'int'. Si el OP realmente tuviera una sobrecarga tomando un 'int' y otro tomando' char * ', la resolución de sobrecarga tendría éxito y elegiría la sobrecarga' int'. Sin embargo, OP usa 'unsigned int' como el tipo de parámetro. Y esas dos conversiones, 'int' ->' unsigned int' vs null puntero constante -> 'char *' son ambiguas. – dyp

+0

@dyp: Si '0' tiene solo un significado, ¿cómo puede estar involucrado en dos conversiones ambiguas con diferentes tipos de inicio? –

1

Uso

p.setval(static_cast<const char *>(0)); 

o

p.setval(static_cast<unsigned int>(0)); 

como lo indica el error, el tipo de 0 es int. Esto se puede convertir fácilmente en unsigned int o const char *. Al hacer el molde manualmente, le está diciendo al compilador qué sobrecarga desea.

1

moldeada el valor por lo que el compilador sabe que funcionan a llamar:

p.setval(static_cast<const char *>(0)); 

Nota, que tiene un fallo de segmentación en su código después de que se compile (dependiendo de la función que realmente quería llamar)

3

reemplace p.setval(0); con lo siguiente.

const unsigned int param = 0; 
p.setval(param); 

De esta manera se sabe con certeza de qué tipo es la constante 0.

2

Esto es ambiguo porque un puntero es solo una dirección, por lo que un int también se puede tratar como un puntero - 0 (an int) se puede convertir a unsigned int o char * igualmente fácilmente.

La respuesta corta es llamar a p.setval() con algo que es inequívocamente uno de los tipos para el que está implementado: unsigned int o char *. p.setval (0U), p.setval ((unsigned int) 0) y p.setval ((char *) 0) compilarán todos.

En general, es una buena idea mantenerse al margen de esta situación, en primer lugar, al no definir funciones sobrecargadas con tipos similares.

+0

+1 para el último párrafo en particular. –

+0

No puedo esperar para C++ 0x, cuando finalmente tendremos la palabra clave nullptr :) –

+0

p.setval ((char *) 0) compilará, pero la aplicación se bloquea. p.setval (0U) funciona bien – Rajesh

12

La solución es muy sencilla si tenemos en cuenta el tipo de valor constante, que debe ser "sin signo int "en lugar de" int ".

En lugar de:

setval(0) 

Uso:

setval(0u) 

El sufijo "u" indica al compilador que este es un entero sin signo. Entonces, no se necesitaría ninguna conversión, y la llamada no sería ambigua.

+1

La mejor respuesta, manera simple y elegante de decirle al compilador –

Cuestiones relacionadas