Calling child method from parent destructor in C ++

class A { public: ~A() { release(); } virtual release() { cout << "~A"; } } class B : public A { release() { cout << "~B"; } } 

When I delete B, only the class method of the class () is called.

What I want to achieve, for each child object, when it is deleted, I want to call the release method, which is redefined in each child class, without manually specifying a destructor for each child with a call for release (I'm lazy), Is it really impossible to achieve this or any other way?

+4
source share
3 answers

Destructors are executed in the reverse order of constructors, so when A destroyed in B its component B already destroyed and no longer exists. Calling a method on a destroyed object gives undefined behavior, and therefore calls to virtual methods always resolve the current class type inside the constructor or destructor.

So basically no, you cannot do this. You will have to write them all.

+6
source

Do not call virtual methods from destructors or constructors - they will not do what you expect from them.

Stop being lazy and write destructors.

+3
source

The solution to this problem is the pre-destruction phase, where you can manually control how the destruction occurs.

Embed your object using the pImpl template. When the packaging object is destroyed, tell pImpl that it will be destroyed before you destroy it.

pImpl can have a virtual PreDestroyable base class that allows child methods to register the PreDestruction that you call during this pre-destruction phase.

 class Destroyable { protected: Destroyable() {}; // must be empty virtual ~Destroyable() { Assert(PreDestroyers.empty()); }; void RegisterPreDestroy( std::function<void()> const& func ) { PreDestroyers.push_back(func) ); private: std::vector<std::function<void()>> PreDestroyers; public: // reverse order, reentrant: void PrepareToDie() { while (!PreDestroyers.empty()) { auto f = PreDestroyers.back(); PreDestroyers.pop_back(); f(); } } }; // handles registration: template<typename T> class HasPreDestroyCode: public virtual Destroyable { // TODO: usual CRTP static or dynamic checks: T* self() { return static_cast<T*>(this); } T const* self() const { return static_cast<T*>(this); } HasPreDestroyCode() { RegisterPreDestroy( [&]() { self()->PreDestroy(); } ); } HasPreDestroyCode( HasPreDestroyCode const& other ) { RegisterPreDestroy( [&]() { self()->PreDestroy(); } ); } HasPreDestroyCode( HasPreDestroyCode const& other ) { RegisterPreDestroy( [&]() { self()->PreDestroy(); } ); } private: HasPreDestroyCode& operator=( HasPreDestroyCode const& other ) = delete; }; class Test: HasPreDestroyCode<Test> { public: void PreDestroy() {} }; 

I wrote this material before C ++ 11, so I have not developed how to handle the movement by creating it. And all this is done at runtime, while it is probably possible to do something like the above, with less runtime data. Something like a list of types in a hierarchy containing pre-destroy code, or something else?

+3
source

All Articles