Cómo resolver el "método virtual puro llamado"
Frecuentes
Visto 58,735 veces
27
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*>
.
3 Respuestas
39
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
14
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
1
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 c++ polymorphism derived-class base-class pure-virtual or haz tu propia pregunta.
Entonces, ¿cómo sé qué instancia de
this
Me refiero a si lo llamo en el constructor derivado. - user869525Probablemente 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-BalloSí, entiendo esto, pero no resuelve mi problema ya que estoy en
SomeClass
no,BaseClass
niDerivedClass
.SomeClass
posee una instancia deBaseClass
yDerivedClass
posee unlist
ofSomeClass
. El destructor enSomeClass
necesita eliminar una instancia deSomeClass
from thelist
dentro deDerivedClass
. - user869525