How to resolve "pure virtual method called"
Solution 1
By the time your destructor is called, the destructor of inherited classes has already been called. Within constructors and destructors, the dynamic type of the object can effectively be considered to be the same as the static type. That is, when you call virtual methods from within your constructors/destructors it's not the overriden versions of them that are called.
If SomePureVirtualMethod
needs to be called at the destructor, then you will have to call it within the destructor of the class where the actual definition of the method you want is.
Solution 2
When you call the virtual
method in the destructor of the Base class SomeClass
it calls the method(SomePureVirtualMethod()
) of the Base class SomeClass
which is a pure virtual method with no definition. And hence the error.
Why does this happen?
The type of this
in constructor or destructor is of the type whose constructor or destructor is being called and hence dynamic dispatch doesn't work in constructors and destructors as you would expect it to work in all other functions.
Why does it crash?
Because calling a pure virtual function from constructor or destructor is an Undefined Behavior.
C++03 10.4/6 states
"Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined."
How to avoid it?
Just ensure that you don't call a pure virtual function from constructor or destructor.
Don't call virtual
methods in constructor or destructor unless you understand the dynamics involved.
Solution 3
There is another reason why this might happen, depending on your compiler and system, and that is from a dangling reference. Paul S. R. Chisholm explains the possible state of freed memory:
- The memory might be marked as deallocated.
- The memory might be deliberately scrambled.
- The memory might be reused.
- The memory might have been left exactly the way it was.
The last is an interesting case. What was the object "exactly the way it was"? In this case, it was an instance of the abstract base class; certainly that's the way the vtbl was left. What happens if we try to call a pure virtual member function for such an object?
"Pure virtual function called".
Related videos on Youtube
user869525
Updated on August 01, 2020Comments
-
user869525 almost 4 years
I understand why this is happening, but I'm stuck trying to resolve it...here is what my code is doing when the error is generated (thus, leading to a crash) when my program exits...
pure virtual method called
SomeClass::~SomeClass() { BaseClassObject->SomePureVirtualMethod(this); }
void DerivedClass::SomePureVirtualMethod(SomeClass* obj) { //Do stuff to remove obj from a collection }
I never have a call to
new SomeClass
but I have aQList<SomeClass*>
which I appendSomeClass*
objects to. The purpose of this destructor inSomeClass
is to tellDerivedClass
to remove a specific instance ofSomeClass
from it's collection ofQList<SomeClass*>
.So, in a concrete example...
BaseClass
=Shape
DerivedClass
=Triangle
SomeClass
=ShapeProperties
which owns a reference toShape
So, I never have a call to
new ShapeProperties
but I have aQList<ShapeProperties*>
inside ofTriangle
. The destructor inShapeProperties
is to tellTriangle
to remove a specific property ofShapeProperties
from it's collection ofQList<ShapeProperties*>
. -
user869525 about 12 yearsThen how do I know which instance of
this
I'm referring to if I call it with in the derived constructor? -
user869525 about 12 yearsI probably misunderstood this, "If
SomePureVirtualMethod
needs to be called at the destructor, then you will have to call it within the destructor of the class where the actual definition of the method you want is." -
K-ballo about 12 years@user869525: In simple words, your call to
SomePureVirtualMethod
from a destructor won't resolve to the most derived override. If you want to call the most derived override, you have to call it from the destructor of the class that implements such override. -
user869525 about 12 yearsYes, I understand this, but it doesn't resolve my issue since I'm in
SomeClass
, notBaseClass
norDerivedClass
.SomeClass
owns an instance ofBaseClass
andDerivedClass
owns alist
ofSomeClass
. The destructor inSomeClass
needs to remove an instance ofSomeClass
from thelist
inside ofDerivedClass
.