c++ - hijo - herencia java
La declaración de uso en la clase derivada no oculta la misma función derivada de la clase base (1)
Echa un vistazo al siguiente código:
struct A {
public:
virtual void f(){std::cout << "in A";};
};
struct B : A{
public:
virtual void f(){std::cout << "in B";};
int a;
};
struct C : B{
using A::f;
void test(){f();}
};
int main()
{
C c;
c.f(); // calls B::f, the final overrider
c.C::f(); // calls A::f because of the using-declaration
c.test(); //calls B::f
return 0;
}
A mi entender, el B::f() en C debería ocultar el A::f() que se lleva a C mediante la declaración de uso; si es así, entonces ¿por qué cC::f() sigue llamando A::f() ?
Si cC::f() llama a A::f() , eso significa que en el ámbito de C , f() siempre debe referirse a A::f() , esta es la función de la declaración de uso. Entonces, ¿por qué en C::test() , la llamada a f() aún se evalúa como B::f() ?
Muy buena pregunta, un caso complicado de búsqueda de nombre.
Básicamente, cuando se busca el nombre f en el alcance de C , siempre encuentra A::f debido a la declaración de uso. Entonces, todas las llamadas cf() , cC::f() f() en C::test() , resuelven el nombre f a A::f .
Luego viene el despacho virtual. Si se llama a una función virtual con un nombre no calificado, se produce un envío dinámico y se llama al anulador final. Esto cubre cf() y la llamada f() en C::test() , ya que no están calificados.
La llamada cC::f() usa un nombre calificado para f , que suprime el envío dinámico y la función a la que se llama el nombre resuelto se llama directamente. Como esa función es A::f (gracias a la declaración de uso), A::f se llama no virtual. Las reglas relevantes son las siguientes (citando el borrador final de C ++ 14 N4140, énfasis mío):
§10.3 / 15
La calificación explícita con el operador de alcance (5.1) suprime el mecanismo de llamada virtual.
§5.2.2 / 1
... Si la función seleccionada no es virtual, o si la expresión-id en la expresión de acceso del miembro de la clase es una id-calificada, se llama a esa función. De lo contrario, se llama a su anulador final (10.3) en el tipo dinámico de la expresión del objeto; dicha llamada se denomina llamada de función virtual.