I came across this:
struct Base {
void* operator new (size_t);
void operator delete (void*);
virtual ~Base () {} // <--- polymorphic
};
struct Derived : Base {};
void Base::operator delete (void *p)
{
Base *pB = static_cast<Base*>(p);
if(dynamic_cast<Derived*>(pB) != 0)
{ /* ... NOT reaching here ? ... */ }
free(p);
}
Now if we do,
Base *p = new Derived;
delete p;
Surprisingly, the condition inside the Base::delete is not satisfied
Am I doing anything wrong ? Or casting from void*
looses the information of Derived*
?
New and Delete operators can be overloaded globally or they can be overloaded for specific classes. If these operators are overloaded using member function for a class, it means that these operators are overloaded only for that specific class.
The dynamic_cast operator ensures that if you convert a pointer to class A to a pointer to class B , the object of type A pointed to by the former belongs to an object of type B or a class derived from B as a base class subobject.
If the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.
So when dynamic_cast for a pointer type fails it returns a null pointer and the caller can check for that, but when it fails for a reference type it can't return a null reference, so an exception is the only reasonable way to signal a problem. Save this answer.
Function operator delete
is a raw-memory deallocation function. It is invoked when the actual object (that used to reside in that memory) has already been destructed. I.e. by the time you get into operator delete
you object has already been wiped out. The memory the pointer points to is essentially "raw", it no longer contains an object. Trying to use any polymorphic functionality on this raw memory is useless - it will not work.
In more formal terms, according to the language standard the lifetime of an object with non-trivial destructor ends once its destructor starts. In your case all destructors have already done their work. The lifetime of the object is already over, while dynamic_cast
requires a "live" object.
P.S. Formally, it is permissible to use dynamic_cast
in a destructor as long as some conditions are met (see 12.7/5), but when all destructors are finished (as in your case), dynamic_cast
is no longer usable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With