llamada a función virtual desde la clase base
Digamos que tenemos:
Class Base
{
virtual void f(){g();};
virtual void g(){//Do some Base related code;}
};
Class Derived : public Base
{
virtual void f(){Base::f();};
virtual void g(){//Do some Derived related code};
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
¿De cuál g()
se llamará Base::f()
? Base::g()
o Derived::g()
?
Gracias...
8 answers
Se llamará a la g de la clase derivada. Si desea llamar a la función en la base, llame a
Base::g();
En su lugar. Si desea llamar a la derivada, pero aún desea que se llame a la versión base, organice que la versión derivada de g llame a la versión base en su primera instrucción:
virtual void g() {
Base::g();
// some work related to derived
}
El hecho de que una función de la base puede llamar a un método virtual y el control se transfiere a la clase derivada se utiliza en el patrón de diseño del método de plantilla. Para C++, es mejor conocido como Interfaz no Virtual. Es ampliamente utilizado también en la biblioteca estándar de C++ (los búferes de flujo de C++, por ejemplo, tienen funciones pub...
que llaman a funciones virtuales que hacen el trabajo real. Por ejemplo pubseekoff
llama al protegido seekoff
). Escribí un ejemplo de eso en esta respuesta: ¿Cómo validas el estado interno de un objeto?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:39
Es el Derivado::g, a menos que llame a g en el constructor de Base. Debido a que el constructor Base es llamado antes de que se construya el objeto Derivado, Derived::g no puede ser llamado lógicamente porque podría manipular variables que aún no han sido construidas, por lo que Base:: g será llamado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-19 04:18:01
PBase es un puntero a una base. pBase = new Derived devuelve un puntero a una Base Derived-Derived is-a.
Así que pBase = nuevo Derivado es válido.
PBase hace referencia a una Base, por lo que se verá Derivada como si fuera una Base.
PBase - > f () llamará Derive:: f ();
Entonces vemos en el código que:
Derive:: f () > > Base::f () g > g () - pero ¿qué g??
Bueno, llama Derive::g() porque es la g a la que pBase "apunta".
Respuesta: Derive:: g ()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-28 20:56:32
Bueno... No estoy seguro de que esto deba compilar. Lo siguiente,
Base *pBase = new Derived;
No es válido a menos que tenga:
Class Derived : public Base
¿Es lo que quieres decir? Si esto es lo que querías decir,
pBase->f();
Entonces la pila de llamadas sería así:
Derived::f()
Base::f()
Derived::g()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-29 19:20:54
Como ha definido g() como virtual, la g() más derivada será buscada en la vtable de la clase y llamada independientemente del tipo de código al que esté accediendo actualmente.
Consulte las preguntas frecuentes de C++ sobre funciones virtuales.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-29 10:15:35
Realmente ejecutando tu código muestra que Derived::g() es llamado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-30 07:30:04
Creo que estás tratando de inventar Patrón de Método de Plantilla
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-29 10:06:30
Se llamará al método de la clase derivada.
Esto se debe a la inclusión de vtables dentro de clases que tienen funciones virtuales y clases que anulan esas funciones. (Esto también se conoce como despacho dinámico.) Esto es lo que realmente está pasando: se crea una vtable para Base
y se crea una vtable para Derived
, porque solo hay una vtable por clase. Debido a que pBase
está llamando a una función que es virtual y anula, un puntero a la vtable para Derived
es called. Llámalo d_ptr
, también conocido como vpointer:
int main()
{
Base *pBase = new Derived;
pBase->d_ptr->f();
return 0;
}
Ahora el d_ptr llama a Derived::f()
, que llama a Base::f()
, que luego mira la tabla v para ver qué g()
usar. Debido a que el vpointer solo conoce g()
en Derived
, ese es el que usamos. Por lo tanto, Derived::g()
se llama.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 02:08:36