que - objetos en c++
¿Qué sucede cuando un destructor llama una función abstracta? (3)
Tengo problemas para entender cuál es el motivo del bloqueo en el siguiente código:
class A {
public:
virtual ~A() { goo(); }
void goo() { absFoo(); }
virtual void absFoo() = 0;
};
class B : public A {
public:
void absFoo() { cout << "In B /n"; }
};
int main()
{
B b1;
b1.goo();
}
El principal imprime "In B" como se esperaba, pero al final, cuando se bloquea, tampoco puedo depurarlo, el compilador muestra un mensaje extraño.
Entonces mi pregunta es, cuando el destructor de A llama "goo ()", ¿se bloquea "absFoo ()" porque nos referimos a una función abstracta?
¿O el compilador realmente busca una definición en las clases derivadas? (Y ya no existe porque fue destruido de antemano, por lo que se bloquea)
Sé que si hubiéramos llamado "absFoo ()" directamente desde el destructor, la razón habría sido la función abstracta. Pero como aquí es una función externa que llama "absFoo ()", tengo problemas para entender la verdadera razón.
¿Qué sucede cuando un destructor llama una función abstracta?
Primero, consideremos lo que sucede cuando un destructor llama a cualquier función virtual (lo mismo se aplica al constructor, por cierto): cuando se llama a una función virtual foo
en el destructor de T
, la llamada no se enviará dinámicamente a una implementación en un tipo derivado (la vida útil de cualquier objeto derivado ya ha finalizado), pero estáticamente a la implementación T::foo
.
Si T::foo
es puramente virtual, entonces llamarlo sin un envío dinámico tendrá un comportamiento indefinido. Eso es lo que sucede cuando una función virtual pura se llama (indirectamente) en un destructor (o constructor).
A medida que el objeto se deconstruye, vtable se actualiza para que coincida con el nuevo estado del objeto.
Dado que ha eliminado la última función, el compilador hará lo que considere oportuno; que, en el caso de una compilación de depuración en Visual Studio, recurrirá a un aborto que informa que se llamó a una función virtual pura.
Sin embargo, vtable no es parte de la norma, es un detalle de implementación y no hay ningún requisito para que su programa se bloquee; es lo que se considera lo más agradable que se puede hacer cuando se llama una función virtual pura.
Solo para complementar la respuesta ya aceptada, esta es la documentación de cppreference .
Cuando se llama a una función virtual directa o indirectamente desde un constructor o desde un destructor (incluso durante la construcción o destrucción de los miembros de datos no estáticos de la clase, por ejemplo, en una lista de inicializadores de miembros), y el objeto al que se aplica la llamada es el Objeto en construcción o destrucción, la función llamada es el anulador final en la clase del constructor o destructor y no uno que lo anule en una clase más derivada.
En otras palabras, durante la construcción o destrucción, las clases más derivadas no existen.