c++ - sobreescribir - Función virtual implementada en la clase base no encontrada por el compilador
polimorfismo puro c++ (2)
Tengo una situación en la que parece que el compilador no encuentra la definición / implementación de la clase base de una función virtual con el mismo nombre que otra función miembro.
struct One {};
struct Two {};
struct Base
{
virtual void func( One & );
virtual void func( Two & ) = 0;
};
struct Derived : public Base
{
virtual void func( Two & );
};
void Base::func( One & )
{}
void Derived::func( Two & )
{}
// elsewhere
void this_fails_to_compile()
{
One one;
Derived d;
d.func( one );
}
Estoy usando Visual C ++ 2008. El mensaje de error es:
error C2664: ''Derived :: func'': no se puede convertir el parámetro 1 de ''One'' a ''Two &''
Pensé que el envío basado en el tipo funcionaría y llamaría a la función de clase base definida. Si agrego una Derived::func( One & )
se compila y se llama correctamente, pero en mi situación, esa versión de la función se puede hacer en la clase base y las clases derivadas generalmente no necesitan implementarla ellas mismas. Actualmente estoy trabajando en ello poniendo una función no virtual con un nombre diferente en la clase base que reenvía la llamada a la función que causa el problema:
// not virtual, although I don''t think that matters
void Base::work_around( One & one )
{
func( one );
}
Eso funciona pero obviamente es menos que ideal.
¿Qué herencia y / o regla de ocultamiento de nombres me estoy perdiendo aquí?
Estás ocultando el método en la clase derivada. La solución más simple es agregar una declaración de uso a la clase derivada.
struct Derived : public Base
{
using Base::func;
virtual void func( Two & );
};
El problema es que cuando el compilador intenta buscar el identificador de func
en la llamada d.func(one)
tiene que hacerlo desde Derived
hacia arriba, pero se detendrá en el primer contexto donde encuentre el identificador de func
, que en este caso se Derived::func
. No se realiza ninguna otra búsqueda y el compilador solo veía Derived::func( Two& )
.
Añadiendo el using Base::func;
Cuando el compilador ve la definición Derived
, incluye todas las declaraciones de Base::func
en el ámbito, y encontrará que hay una Base::func( One & )
que no se anuló en Derived
.
Tenga en cuenta también que si estuviera llamando a través de una referencia a Base
, entonces el compilador encontraría las dos sobrecargas de func
y enviaría de forma adecuada cada una al overrider final.
Derived d;
Base & b = d;
b.func( one ); // ok even without the ''using Base::func;'' directive
Oculta la func(One&)
en Derived
. Podrías usar el nombre completo:
d.Base::func( one );