I have 2 classes A and B, which looks like this
class A{
public:
~A(){/* do something */};
};
class B : public A{
public:
~B(){/* do something */};
};
I want to avoid calling ~A()
when ~B()
is called. I found this post said that std::shared_ptr
can customize deleter to control destructor. But I'm working on a Qt project which uses QScopedPointer
to declare B.
Now my question is:
How to customize the QScopedPointerDeleter
to avoid calling destructor of parent A?
CodePudding user response:
The good guy
Don't do it. Solve the actual problem in a clean way.
The bad guy - I really want to do it
WARNING Keep in mind that you may get in trouble using this approach, f.ex. by creating memory leaks or undefined behavior.
Note that calling the child destructor ~B
, without executing the parent/base destructor ~A
isn't possible:
Even when the destructor is called directly (e.g. obj.~Foo();), the return statement in ~Foo() does not return control to the caller immediately: it calls all those member and base destructors first. [1]
However, you can move the logic of ~B
to another member function and call that one instead:
class B : public A{
public:
~B(){/* do something */};
void DestructWithoutParent () {
/* do something */
/* call destructor of members*/
}
};
Note that you should now call the destructor of your members (if any) explicitly.
Now you can release the memory of your B
object manually and call your custom destructor function (see this answer for more information and why you shouldn't use this approach):
B *b = new B();
b->DestructWithoutParent (); // calls the 'destructor' of B without calling ~A
operator delete(b); // free memory of b
Note that the heap memory owned by A
(f.ex. by smart pointer members of A
), isn't released in this way. It may also violate the assumptions made by the programmer of class A, possibly resulting in undefined behavior.
Integrating this with QScopedPointer
[2]:
struct BDeleter {
static inline void cleanup(B *b)
{
b->DestructWithoutParent (); // calls the 'destructor' of B without calling ~A
operator delete(b); // free memory of b
}
};
QScopedPointer<B, BDeleter> b(new B);