Hello again! In this video, we are going to look at catch-all handlers.
We can write a handler which can catch any type of exception.
We just put "..." as the exception type.
So we write our catch handler like this, with three dots as the exception type.
By the way, when I put three dots in blue, that just means arbitrary code.
So here we have any code that might throw an exception.
It does not matter what the code is.
When we have three dots in black, that is C++ syntax.
So we use that with catch handlers and also with templates, which we will see later on in the course.
So this code could throw any type of exception, not just any class from the exception hierarchy, but
also built-in types, library classes, classes
you write yourself and so on.
And the reason for that is that C++ had exceptions before it had the standard exception hierarchy.
So let's look at some code.
We have a try block. We have a catch handler which can handle any type of exception, with the three
dots. When we're inside the body of this cash handler -
You will notice there is no actual arguments here, so we do not have any variables, so we do not know anything
about the type of this exception.
So all we can do really is just log it, print out a message.
So let's see what happens if we throw an int.
So there we are, so it works, and it gets caught by this handler.
What about a C-style string?
OK, and...
now, the vector access.
So what is going to happen here?
Well, this is going to throw the out_of_range error again, the program will look for a handler immediately
following this try block.
It will find one which can take anything.
So we expect to see the same message again.
And that is what we get.
If we had a more specific handler.
For the standard exception base class, for example.
Then we would have a variable and we have some information. So we can call the what() member function.
So when the exception is thrown and the program is looking for a handler, this will be the first one
which matches, because out_of_range is a sub-class of the standard exception.
And so we should see - yes, there we are.
We get the usual exception. Vector error.
So is this really useful? I mean, we have all these exception types in the exception hierarchy, so
we do not really need to throw around ints or C-style strings, or even C++ strings.
Well, it is useful as a fallback.
So let's say we have some code that might throw an exception.
We have a handler for network connection errors, and its child classes.
We have one for data error and its child classes.
If neither of these match, then the next one is this one, which will handle anything.
So this will catch any exception, which is not caught by the handlers above it.
So this will catch any exception, which is not caught by the handlers above it, so this is useful
for alerting us that we have missed an exception.
We need to add another catch block in here somewhere.
And you can also do this with your main function.
You can put a catch-all handler in main().
Normally, if you have an exception which is not handled, then the program will terminate.
But the program also terminates because of a memory access error, or some other bug or undefined behaviour.
So you do not really know. With this one,
if there is any exception thrown during the program, which is not handled, then it will be caught by
this catch block.
So we do at least know that there is an underhanded exception, somewhere in the code, and we can start
investigating.
And you can also use the trick with the exception.
So we have the try blocks for network connection error, data error.
If there is something which is in the exception hierarchy, but not covered by those, then we can catch it here
and get some information.
And if by some chance, there is some weird exception, that maybe a third party library throws, then we
will at least know that there is an unhandled exception.
So a catch-all handler is useful for testing your code.
It will help you find situations where you have missed out catch blocks, or overlooked error conditions.
If you are debugging, though, it is actually not helpful.
The best thing to do there is to not handle the error and lets the debugger trap it. Then you can actually
inspect the object in the debugger, and that will give you more useful information than just a vague
message saying there is an unhandled exception.
There is no information about the error condition, there is no type information. And also it does not
capture other events which might cause your program to have a premature exit.
So in Unix, things like signals, or structured
exceptions in Windows.
OK, so that is it for this feature.
I will see you next time, but until then, keep coding!