modo hijo herencia ejemplos destructores derivadas derivada constructores clases clase c++ using-declaration

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.