What is Constructor in cpp
Constructors do not have return type and so they cannot return error codes. How are errors or exceptions handled in constructors? What if the calls that you make in the constructor can actually throw exceptions? How do you let the caller know something bad happened in a constructor?
There are a few ways to do robust error/exception handling in constructors
1. Do as little in the constructor has you can. Then provide an Init() function in the constructor, which does the normal initialization stuff. The user can then call this function after creating an object. The problem here is, its up to the user to actually call the Init() function. The user could potentially miss this step, making this method error prone. However, there are a lot of places where this methodology is used. You are trying to eliminate error handling in the constructor by using this method
2. Another way to do this is by putting the object in a Zombie state. This is one approach you can take especially if you do not have the option of using exceptions. When you go with this option, you will also to do provide a function that will check the state of the object after construction. The downsides to this option is that, its up to the user to do these checks and the users will need to do this every time one attempts to create an object. It's usually always better and cleaner to throw an exception instead. Use the Zombie option as a last resort.
3. The downsides to the above methods can be reduced by making the constructor private or protected, expose a CreateInstance() public method, and do all the error handling here rather than leave it to the user. But sometimes, its not possible to handle all the error conditions in a generic manner and you will need to throw an exception.
4. If an exception is thrown in the constructor, the destructor will not get called. So you need to handle and clean up as much as you can before you leave the constructor. The best way to do this is using the "resource allocation is initialization" technique. I will cover this topic separately in a future post. But the basic idea is to assign resource allocation and cleanup to other objects. Basically, you are trying to get allocation out of the way (indirect) so that you don't have to do it explicitly. When you don't allocate something directly, you don't have to release it either because it will be done by the component or class who deals with it. E.g. If you need to allocate some memory or open up a file, You can use smart objects (smart pointer, auto_ptr, smart file handlers etc..) instead of calling new or fopen directly. When you do this, and if an exception is thrown in your constructor, the smart objects will automatically release the resources it acquired, as the stack unwinds. If you do not use the "resource allocation is initialization" technique, the user will need to wrap the statements in try/catch block and rethrow after cleaning up the mess, something like what the finally block does in Java or C#. Although this works in theory, it's up to the user to make this work and it also always a source of errors and bugs (esp. memory and handle leaks) and is messy
As you have seen, there is no "one size fits all" rule to do error/exception handling in constructors. I have listed the most commonly used methods and one of these should work most of the time.
No comments:
Post a Comment