Due to the well-known issues with calling virtual methods from inside constructors and destructors, I commonly end up with classes that need a final-setup method to be called just after their constructor, and a pre-teardown method to be called just before their destructor, like this:
MyObject * obj = new MyObject;
obj->Initialize(); // virtual method call, required after ctor for (obj) to run properly
[...]
obj->AboutToDelete(); // virtual method call, required before dtor for (obj) to clean up properly
delete obj;
This works, but it carries with it the risk that the caller will forget to call either or both of those methods at the appropriate times.
So the question is: Is there any way in C++ to get those methods to be called automatically, so the caller doesn't have to remember to do call them? (I'm guessing there isn't, but I thought I'd ask anyway just in case there is some clever way to do it)
You can call a virtual function in a constructor. The Objects are constructed from the base up, “base before derived”.
As a general rule, you should never call virtual functions in constructors or destructors. If you do, those calls will never go to a more derived class than the currently executing constructor or destructor. In other words, during construction and destruction, virtual functions aren't virtual.
Calling virtual functions in constructors makes your code extremely sensitive to the implementation details in derived classes. You can't control what derived classes do. Code that calls virtual functions in constructors is very brittle.
}; Similarly, it is permissible to call a virtual function from a constructor or destructor of a class that has the final class-virt-specifier, as in this example.
While there is no automated way, you could force the users hand by denying users access to the destructor on that type and declaring a special delete method. In this method you could do the virtual calls you'd like. Creation can take a similar approach which a static factory method.
class MyObject {
...
public:
static MyObject* Create() {
MyObject* pObject = new MyObject();
pObject->Initialize();
return pObject;
}
Delete() {
this->AboutToDelete();
delete this;
}
private:
MyObject() { ... }
virtual ~MyObject() { ... }
};
Now it is not possible to call "delete obj;" unless the call site has access to MyObject private members.
The best I can think of is for you to implement your own smart pointer with a static Create method that news up an instance and calls Initialize, and in its destructor calls AboutToDelete and then delete.
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