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.