que - polimorfismo puro c++
¿Qué puede causar una llamada de función virtual pura en C++? (3)
"El error más común que he visto que causa esto es llamar a una función virtual desde un constructor o destructor de clase base".
Cuando se construye un objeto, el puntero a la tabla de envío virtual se dirige inicialmente a la superclase más alta, y solo se actualiza a medida que las clases intermedias completan la construcción. Por lo tanto, puede llamar accidentalmente a la implementación virtual pura hasta el punto en que una subclase (con su propia implementación de funciones primordiales) complete la construcción. Esa podría ser la subclase más derivada, o cualquier punto intermedio.
Puede suceder si sigue un puntero a un objeto parcialmente construido (por ejemplo, en una condición de carrera debido a operaciones asincrónicas o con rosca).
Si un compilador tiene motivos para pensar que conoce el tipo real al que apunta una clase de puntero a base, puede razonablemente pasar por alto el envío virtual. Puede confundirlo haciendo algo con un comportamiento indefinido, como un reparto de reinterpretación.
Durante la destrucción, la tabla de envío virtual debe revertirse a medida que se destruyen las clases derivadas, por lo que la implementación virtual pura puede invocarse nuevamente.
Después de la destrucción, el uso continuado del objeto a través de punteros o referencias "colgantes" puede invocar la función virtual pura, pero no existe un comportamiento definido en tales situaciones.
Enseño una clase de programación en C ++ y he visto suficientes clases de errores que tengo una buena idea de cómo diagnosticar errores comunes en C ++. Sin embargo, hay un tipo importante de error para el cual mi intuición no es particularmente buena: ¿qué errores de programación causan llamadas a funciones virtuales puras? El error más común que he visto que causa esto es llamar a una función virtual desde un constructor o destructor de clase base. ¿Hay algún otro que deba tener en cuenta a la hora de ayudar a depurar el código del alumno?
Aquí hay algunos casos en los que puede ocurrir una llamada virtual pura.
- Usando un puntero colgante : el puntero no es un objeto válido, por lo que la tabla virtual a la que apunta es solo una memoria aleatoria que puede contener NULL
- El mal reparto usando
static_cast
al tipo incorrecto (o molde de estilo C) también puede hacer que el objeto al que apunta no tenga los métodos correctos en su tabla virtual (en este caso al menos realmente es una tabla virtual diferente a la opción anterior ). - La DLL ha sido descargada : si el objeto al que está reteniendo se creó en un archivo de objeto compartido (DLL, por lo tanto, sl) que se ha descargado nuevamente, la memoria puede ponerse a cero ahora.
Esto puede ocurrir, por ejemplo, cuando la referencia o el puntero a un objeto apunta a una ubicación NULA, y utiliza la referencia o puntero del objeto para llamar a una función virtual en la clase. Por ejemplo:
std::vector <DerivedClass> objContainer;
if (!objContainer.empty())
const BaseClass& objRef = objContainer.front();
// Do some processing using objRef and then you erase the first
// element of objContainer
objContainer.erase(objContainer.begin());
const std::string& name = objRef.name();
// -> (name() is a pure virtual function in base class,
// which has been implemented in DerivedClass).
En este punto, el objeto almacenado en objContainer [0] no existe. Cuando la tabla virtual está indexada, no se encuentra una ubicación de memoria válida. Por lo tanto, se emite un error de tiempo de ejecución que dice "función virtual pura llamada".