In my experience as software developer, I noticed that there are lots of people that write in C++, but do not use exceptions. They prefer to use return codes instead. I guess that this is caused by the late addition of exceptions in the C++ standard. Whatever the reason is, personally, I prefer to use exceptions as an error handling technique.
Almost 10 years ago I started programing in Object Pascal (Borland Delphi). It was really popular in Bulgaria at that time. I used to like it and I still think that Pascal is the best programming language for education purposes. In my opinion VCL is well designed framework, that is teaching developers good programming practices. Anyway, exceptions are widely used in VCL. So I got used to exceptions and when I moved to C++, I continued using this error handling mechanism.
So why use exceptions?
Overall, exceptions can improve software quality, but the most important reason in favor of their use is that unlike return codes exceptions can not be ignored. If an exception is thrown someone will have to catch it or the program will be terminated. There is no mercy .
Apart from that, exceptions eliminate one of the reasons for if statements. As we all know if statements are evil (grrr I hate nested ifs). When used for error handling if statements are adding unnecessary control flow complexity. Writing unit tests, reading and testing the code becomes difficult.
Another advantage of exceptions is that the error handling is consistent across different modules.
Syntax (or going back to school)
The exception mechanisms consists of try blocks, catch handlers, throw expressions and exception specifications:
ClassA::method(void* p) throw1(Exception)
{
try2
{
if (null == p)
throw Exception3;
}
catch4(const Exception&) {
//Some code
throw5;
}
}
1. Exception specification – a list of exceptions that a function can throw. It’s not enforced by the complier. Empty specifications states that the function doesn’t throw exceptions. If an exception is thrown that is not in the list, the application will be terminated. That’s why it’s recommended to use empty specifications only. An exception different from the one(s) in the specification might come from a nested function call for example.
2. Try block – area of the code that detects exceptions.
3. Throw expression – raises exception. C++ allows you to throw virtually anything, but it’s best to throw objects. I prefer to derive my exceptions classes from the base exception class of the framework I’m using. For example when developing MFC applications I use CException, when I use STL my exceptions are derived from the std::exception class, etc.
4. Catch handler – has signature denoting an exception type.
It’s best to catch by reference, this way avoiding the overhead from copy constructors. There are some exceptions though. For example in MFC the exceptions are thrown in the heap, not in the stack, so you’ve got to catch by pointer. In MFC don’t forget to invoke the Delete() method after you’re done with the exception.
You can catch a specific exception (like in the sample above) or you can catch all exceptions:
catch(…)
Don’t forget to order the catch handlers from the more specific to the more generic ones. The catch all handler should be last.
5. Rethrow – useful when some preliminary processing is needed.
Read more: Vladislav online