Professional C__ - Marc Gregoire [157]
C programmers may be familiar with a mechanism known as setjmp()/longjmp(). This mechanism cannot be used correctly in C++, because it bypasses scoped destructors on the stack. You should avoid it at all cost, even in C programs; therefor this book will not explain the details of how to use it.
Exceptions provide an easier, more consistent, and safer mechanism for error handling. There are several specific advantages of exceptions over the ad hoc approaches in C and C++.
When return codes are used as an error reporting mechanism, a defect is that a caller may choose to ignore the return codes, or process them only locally without propagating them upwards, even though higher-level callers need to know there was a lower-level failure. Exceptions cannot be ignored: If your program fails to catch an exception, it will terminate.
When integer return codes are used, they generally do not contain sufficient information. You can use exceptions to pass as much information as you want from the code that finds the error to the code that handles it. Exceptions can also be used to communicate information other than errors, though many programmers consider that an abuse of the exception mechanism.
Exception handling can skip levels of the call stack. That is, a function can handle an error that occurred several function calls down the stack, without error-handling code in the intermediate functions. Return codes require each level of the call stack to clean up explicitly after the previous level.
Why Exceptions in C++ Are a Bad Thing
In some compilers (fewer and fewer these days), exception handling added a tiny amount of overhead to any function that had an exception handler. In modern compilers, this overhead is so small or even non-existing, so that you can ignore it. Do not assume that the urban legend about exceptions introducing serious overhead is true; you have to check it out in your compiler.
Exception handling is not enforced in C++. For example, in Java a function that does not specify a list of possible exceptions that it can throw is not allowed to throw any exceptions. In C++, it is just the opposite: a function that does not specify a list of exceptions can throw any exception it wants! Additionally, the exception list is not enforced at compile time in C++, meaning that the exception list of a function can be violated at run time. Note that some tools, such as using /Analyze with Microsoft VC++, will check exceptions and report potential problems.
Our Recommendation
We recommend exceptions as a useful mechanism for error handling. We feel that the structure and error-handling formalization that exceptions provide outweigh the less desirable aspects. Thus, the remainder of this chapter focuses on exceptions. Also, many popular libraries, such as the STL and Boost use exceptions, so you need to be prepared to handle them. We recommend you read the rest of this chapter, because you should not be surprised by the experience of having an exception thrown.
EXCEPTION MECHANICS
Exceptional situations arise frequently in file input and output. The following is a function to open a file, read a list of integers from the file, and store the integers in the supplied std::vector data structure. A vector is a dynamic array. You can add elements to it by using the push_back() method, and access them with array notation.
void readIntegerFile(const string& fileName, vector { ifstream istr; int temp; istr.open(fileName.c_str()); // Read the integers one by one and add them to the vector. while (istr >> temp) { dest.push_back(temp); } } Code snippet from ReadIntegerFile\NoExceptionHandling.cpp The following line keeps reading values from the ifstream until the end of the file is reached or until an error occurs. while (istr >> temp) { This works because the >> operator returns a reference to the ifstream object itself. Additionally, ifstream provides a bool() conversion operator implemented