Hello again! In this video, we are going to look at the subclasses of standard exception.
So the immediate subclasses are bad_alloc, which is for memory allocation errors and bad_cast
for when a dynamic cast fails.
And then there are two sub-hierarchies, for logic errors and run-time errors.
In the logic error hierarchy, we have out_of_range. So we have seen that with the at() member function of vector.
This is thrown when we try to access an element outside the defined range. invalid_argument.
So for example, stoi() takes a string and returns an int.
But if the argument cannot be converted to a number, then the invalid_argument is thrown.
So that is any case where the argument is not acceptable.
domain_error.
If we have something which takes a date, and we give some invalid date, like the 31st of February,
then that is outside the domain of applicable values.
And length_error. If we try to append too many elements to a string, then that will exceed the length limit of
the object.
For runtime_error, these are more numerical. overflow_error means that the result is too large for the
variable.
So there are too many digits to be stored.
underflow_error means that the result of a floating-point computation is too small. There
are too many zeros after the decimal points, before you get to the actual, non-zero digits. And then
a range_error we have some intermediate result which cannot be represented.
So you might think there are lots of places where the standard library could use exceptions.
So here is an example with the square root function.
This is from the header.
It has a precondition, which is that the argument must be a positive number.
So if we call it with -1, we violate the precondition
and we get a logic error. And -1 is outside the range of acceptable values, so we should get a
domain_error exception, and that should get caught by this catch block.
So let's see what happens.
And we get this weird-looking result. minus nan brackets ind. So obviously, we did not get an exception.
Otherwise, it would have been caught.
So the function has actually completed and returned. And the value that it returned is "not a number".
So this is something from the floating-point implementation.
If you get something which cannot be represented as a floating point number, like dividing by 0
or getting the square root of -1, then the result is NaN. "Not a number".
By default, the C++ streams do not throw exceptions.
I think the argument is, that it is very easy to check the stream's state. And if you want an exception,
you can throw one yourself.
But in C++11, you can actually enable exceptions.
To do that, you need to call the exceptions() member function for the object, for the stream object, and
then you need to say which error conditions you want to cause an exception.
So in this case, if fail_bit or bad_bit is set, "ifile" is going to throw an exception.
So let's try that out. We need to #include to get these input/output exceptions.
We create a stream object, an input file stream.
Then we enable exceptions, like we did on the slide. And then we have a try block, where we have an operation
that might throw an exception. If this "txt" file is not available.
If it does not exist or we are not allowed to access it, then this will throw an exception which should
get caught here.
So let's see what happens.
Right, so we do get the exception.
So this has thrown an exception because the file does not actually exist.
The message is maybe not very user friendly, but it is there.
So why does the C++ library avoid using exceptions so much?
Well, the answer really is efficiency.
The library has to work with every kind of application on every kind of hardware that supports C++.
And if you are going to be checking for exceptions and handling them, then that will require extra
code, and sometimes that may not be acceptable.
For example, the square root function is already quite slow compared to doing basic arithmetic operations.
If you are doing numeric programming, or games, or multimedia.
Then having a square root which checks and throws exceptions could add too much overhead.
However, there are third party libraries which use exceptions, and of course, we are allowed to use
them in our own code.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!