En este ejemplo, las clases Foo
y Bar
se proporcionan desde una biblioteca. Mi clase Baz
hereda de ambos.
struct Foo
{
void do_stuff (int, int);
};
struct Bar
{
virtual void do_stuff (float) = 0;
};
struct Baz : public Foo, public Bar
{
void func ()
{
do_stuff (1.1f); // ERROR HERE
}
};
struct BazImpl : public Baz
{
void do_stuff (float) override {};
};
int main ()
{
BazImpl () .func ();
}
Me sale el error de compilación reference to ‘do_stuff’ is ambiguous
que me parece falso porque las dos firmas de funciones son completamente diferentes. Si do_stuff
no fuera virtual, podría llamar Bar::do_stuff
para desambiguarlo, pero al hacerlo se rompe el polimorfismo y se produce un error de enlace.
¿Puedo hacer una func
llamada virtual do_stuff
sin renombrar cosas?
Respuestas:
Puedes hacerlo:
Probado con wandbox gcc más reciente y se compila bien. Creo que es el mismo caso con sobrecargas de funciones, una vez que sobrecargas una no puedes usar implementaciones de clase base sin ellas
using
.De hecho, esto no tiene nada que ver con las funciones virtuales. El siguiente ejemplo tiene el mismo error
GCC 9.2.0 error: reference to 'do_stuff' is ambiguous
:Posible pregunta relacionada
fuente
La búsqueda de nombres y la resolución de sobrecarga son diferentes. El nombre debe encontrarse primero en un ámbito, es decir, debemos encontrar uno
X
para quedo_stuff
se resuelva el nombreX::do_stuff
, independientemente del uso del nombre, y luego seleccione la resolución de sobrecarga entre las diferentes declaraciones deX::do_stuff
.El proceso NO es identificar todos esos casos
A::do_stuff
,B::do_stuff
etc. que son visibles, y luego realizar una resolución de sobrecarga entre la unión de eso. En cambio, se debe identificar un solo alcance para el nombre.En este código:
Baz
no contiene el nombredo_stuff
, por lo que se pueden buscar las clases base. Pero el nombre aparece en dos bases diferentes, por lo que la búsqueda de nombres no puede identificar un alcance. Nunca llegamos tan lejos como la resolución de sobrecarga.La solución sugerida en la otra respuesta funciona porque introduce el nombre
do_stuff
al alcance deBaz
, y también introduce 2 sobrecargas para el nombre. Por lo tanto, la búsqueda de nombres determina esedo_stuff
medioBaz::do_stuff
y luego selecciona la resolución de sobrecarga de las dos funciones que se conocen comoBaz::do_stuff
.Por otro lado, el sombreado es otra consecuencia de la búsqueda de nombres (no es una regla en sí misma). La búsqueda de nombre selecciona el alcance interno, por lo que cualquier cosa en el alcance externo no coincide.
Otro factor de complicación ocurre cuando la búsqueda dependiente de argumentos está en juego. Para resumir muy brevemente, la búsqueda de nombres se realiza varias veces para una llamada de función con argumentos de tipo de clase: la versión básica como se describe en mi respuesta, y luego nuevamente para cada tipo de argumento. Luego, la unión de los ámbitos encontrados entra en el conjunto de sobrecarga. Pero eso no se aplica a su ejemplo ya que su función solo tiene parámetros de tipo incorporado.
fuente