Cómo resolver el "método virtual puro llamado"

Entiendo por qué sucede esto, pero estoy atascado tratando de resolverlo... esto es lo que hace mi código cuando se genera el error (lo que provoca un bloqueo) cuando mi programa sale...

pure virtual method called

SomeClass::~SomeClass()
{
   BaseClassObject->SomePureVirtualMethod(this);
}

void DerivedClass::SomePureVirtualMethod(SomeClass* obj)
{
    //Do stuff to remove obj from a collection
}

Nunca tengo una llamada para new SomeClass pero tengo un QList<SomeClass*> que agrego SomeClass* objetos a. El propósito de este destructor en SomeClass es decir DerivedClass para eliminar una instancia específica de SomeClass de su colección de QList<SomeClass*>.

Entonces, en un ejemplo concreto...

BaseClass = Shape

DerivedClass = Triangle

SomeClass = ShapeProperties que posee una referencia a Shape

Entonces, nunca tengo una llamada para new ShapeProperties pero tengo un QList<ShapeProperties*> dentro de Triangle. El destructor en ShapeProperties es decir Triangle para eliminar una propiedad específica de ShapeProperties de su colección de QList<ShapeProperties*>.

preguntado el 22 de mayo de 12 a las 18:05

3 Respuestas

Cuando se llama a su destructor, ya se ha llamado al destructor de clases heredadas. Dentro de los constructores y destructores, el tipo dinámico del objeto puede considerarse efectivamente como el mismo que el tipo estático. Es decir, cuando llama a métodos virtuales desde dentro de sus constructores/destructores, no son las versiones anuladas de ellos las que se llaman.

If SomePureVirtualMethod debe llamarse en el destructor, luego tendrá que llamarlo dentro del destructor de la clase donde está la definición real del método que desea.

contestado el 22 de mayo de 12 a las 18:05

Entonces, ¿cómo sé qué instancia de this Me refiero a si lo llamo en el constructor derivado. - user869525

Probablemente entendí mal esto, "Si SomePureVirtualMethod debe llamarse en el destructor, luego tendrá que llamarlo dentro del destructor de la clase donde está la definición real del método que desea". - user869525

@user869525: En palabras simples, su llamada a SomePureVirtualMethod de un destructor no se resolverá en la anulación más derivada. Si desea llamar a la anulación más derivada, debe llamarla desde el destructor de la clase que implementa dicha anulación. - K-Ballo

Sí, entiendo esto, pero no resuelve mi problema ya que estoy en SomeClassno, BaseClass ni DerivedClass.SomeClass posee una instancia de BaseClass y DerivedClass posee un list of SomeClass. El destructor en SomeClass necesita eliminar una instancia de SomeClass from the list dentro de DerivedClass. - user869525

Cuando llamas al virtual método en el destructor de la clase Base SomeClass llama al método(SomePureVirtualMethod()) de la clase Base SomeClass que es un método virtual puro sin definición. Y de ahí el error.

¿Por qué sucede esto?
El tipo de this in constructor o destructor es del tipo cuyo constructor o destructor se está llamando y, por lo tanto, el envío dinámico no funciona en constructores y destructores como se esperaría que funcionara en todas las demás funciones.

¿Por qué se bloquea?
Porque llamar a una función virtual pura desde el constructor o el destructor es un Comportamiento indefinido.

C ++ 03 10.4 / 6 estados

"Las funciones miembro se pueden llamar desde un constructor (o destructor) de una clase abstracta; el efecto de hacer una llamada virtual (10.3) a una función virtual pura directa o indirectamente para el objeto que se crea (o destruye) a partir de dicho constructor ( o destructor) no está definido ".

¿Cómo evitarlo?
Solo asegúrese de no llamar a una función virtual pura desde el constructor o el destructor.
No llames virtual métodos en constructor o destructor a menos que comprenda la dinámica involucrada.

contestado el 22 de mayo de 12 a las 18:05

Hay otra razón por la que esto podría suceder, dependiendo de su compilador y sistema, y ​​es por una referencia pendiente. Paul SR Chisholm explica el posible estado de la memoria liberada:

  • La memoria puede marcarse como desasignada.
  • La memoria podría estar codificada deliberadamente.
  • La memoria puede ser reutilizada.
  • El recuerdo podría haber quedado exactamente como estaba.

El último es un caso interesante. ¿Cuál era el objeto "exactamente como era"? En este caso, fue una instancia de la clase base abstracta; ciertamente así quedó el vtbl. ¿Qué sucede si tratamos de llamar a una función miembro virtual pura para tal objeto?

"Función virtual pura llamada".

Respondido 01 ago 20, 00:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.