WEBVTT

00:00.120 --> 00:08.670
Hello again! In this video, we are going to look at try and catch blocks. A catch look can only appear after a try block,

00:08.880 --> 00:12.060
so we have the try block, immediately followed by a catch block.

00:12.780 --> 00:18.330
And if an exception is thrown in the try block, then that catch block is going to be the first place

00:18.330 --> 00:21.780
the program will look in for a handler for that exception.

00:22.560 --> 00:25.680
We can have more than one catch block for the same try block.

00:26.250 --> 00:31.590
And in fact, if we want to handle exceptions which can have different static types, we need to do

00:31.590 --> 00:31.860
that.

00:32.490 --> 00:36.360
We need to have one catch block for each static type.

00:38.720 --> 00:44.450
If there is any choice about which catch block can handle a particular exception, it will be the first

00:44.450 --> 00:45.980
one that appears in the source code.

00:48.010 --> 00:52.630
So let's have a look at this. We have our vector access, inside a try block.

00:53.620 --> 01:00.760
We have two handlers, one for the base class exception, and one for the derived class, out_of_range.

01:01.270 --> 01:04.240
This is going to be the actual exception that is thrown by this code.

01:04.840 --> 01:07.360
So, which catch block do you think is going to handle it?

01:09.000 --> 01:09.690
Let's find out.

01:12.250 --> 01:14.110
So it is actually the base class exception.

01:14.470 --> 01:16.600
It is the first one that appears in the source code.

01:17.230 --> 01:22.060
So even though this one is actually more specific, the exception one gets called first.

01:23.130 --> 01:31.800
If we move the out_of_range one, so it goes above the exception handler, then that is going to be the

01:31.800 --> 01:34.380
first one which can handle the out_of_range exception.

01:34.830 --> 01:37.760
So we expect that one to be called and yes, there it is.

01:42.790 --> 01:49.450
So this means if you have an inheritance hierarchy, you need to put the catch handlers upside down. So

01:49.450 --> 01:53.860
the child classes go at the top, and then the base class goes at the bottom.

01:55.860 --> 02:01.550
So normally we use the standard exception hierarchy. And to make this work in the way that we expect,

02:01.560 --> 02:04.500
we put the catch blocks in reverse order.

02:04.860 --> 02:09.210
So the most derived one comes first and the base class comes last.

02:12.010 --> 02:17.470
When we are writing an exception handler, there are some things we should bear in mind. As we have already

02:17.470 --> 02:23.830
discussed, the handler should take the exception object by reference, and that will allow polymorphism

02:23.830 --> 02:24.280
to work.

02:24.610 --> 02:29.680
So when you call virtual member functions, like what(), you will get the right version of the function for

02:29.680 --> 02:35.260
the object that was thrown. And also, you should make that a const reference, unless you actually need to

02:35.260 --> 02:36.580
modify the exception object.

02:37.030 --> 02:38.590
So that is just the usual rule, really.

02:40.870 --> 02:46.390
When the program is executing inside a catch block, this implies that something unusual has happened,

02:46.390 --> 02:49.530
which is outside the normal control flow.

02:49.990 --> 02:52.960
So the program may be in an unstable state.

02:53.350 --> 02:56.650
We need to be careful that we do not disturb it any further.

02:57.280 --> 03:03.160
So we should avoid things like allocating memory, creating new variables and calling functions.

03:04.330 --> 03:08.350
If we do need any variables, we should try to use built-in ones if we can.

03:10.880 --> 03:13.530
Never do anything which might throw a new exception.

03:13.550 --> 03:14.660
That is a very bad idea.

03:15.560 --> 03:18.500
And keep the code very short and very simple.

03:21.780 --> 03:27.210
We are allowed to put a try-catch block inside another try block, so we can have nested

03:27.630 --> 03:28.740
try-catch blocks.

03:29.340 --> 03:34.920
So in here we have a try block and a catch handler, for bad_alloc.

03:35.400 --> 03:37.650
This is another subclass of exception.

03:38.100 --> 03:40.290
It gets thrown when there is a memory allocation error.

03:40.650 --> 03:41.700
So, calling new().

03:43.020 --> 03:47.130
It is actually very hard to get this on modern computers, because they do not run out of memory.

03:47.520 --> 03:49.650
They just run very, very slowly instead.

03:51.510 --> 03:57.240
So if we get the bad_alloc exception thrown in this block, it will be handled in this catch handler.

03:57.720 --> 04:03.270
If we get some other exception thrown, then the program will jump out of this inner try block, into the

04:03.270 --> 04:06.360
enclosing scope. Which is this outer try block.

04:06.900 --> 04:09.120
And then it will look for another exception handler.

04:09.870 --> 04:16.590
And if the exception is anything in the standard exception hierarchy, then this handler will handle

04:16.590 --> 04:16.800
it.

04:18.690 --> 04:23.340
So here is an example. We have our favorite vector access again, in the try block.

04:24.590 --> 04:26.930
The catch block for this only handles bad_alloc.

04:27.200 --> 04:32.690
So if there is some kind of memory allocation error, when the program creates this vector, we might

04:32.690 --> 04:34.760
get this catch handler invoked.

04:36.420 --> 04:41.640
Otherwise, it should go and try to do the access. And then the out_of_range exception will be thrown again.

04:42.270 --> 04:43.620
There is no handler in this

04:44.220 --> 04:48.090
try-catch block, so the program is going to jump out into the enclosing scope.

04:48.810 --> 04:50.420
It will look for a handler here.

04:50.430 --> 04:55.770
And because out_of_range is a subclass of exception, this handler is going to be invoked.

04:58.090 --> 04:58.720
And there we are.

05:02.770 --> 05:07.000
One of the advantages of exceptions is that we can handle errors in a different place from where they

05:07.000 --> 05:07.420
occur.

05:08.140 --> 05:14.150
Let's say, for example, we have some function that does data processing, and it calls another function

05:14.150 --> 05:16.210
to actually get a file.

05:16.600 --> 05:18.850
And this code in here could throw an exception.

05:19.750 --> 05:26.140
Supposing we want to handle all the errors in this process_data function(). So how do we set that

05:26.140 --> 05:26.350
up?

05:27.520 --> 05:28.540
It is actually very easy.

05:29.230 --> 05:35.350
We do nothing at all in get_file(), as far as exceptions are concerned, and we call the get_file() function

05:35.350 --> 05:38.470
from inside a try-catch block in process_data().

05:38.920 --> 05:44.770
So we have our process_data() function, which calls get_file() inside the try block. if any exceptions are

05:44.770 --> 05:45.520
thrown in here.

05:45.910 --> 05:46.780
There are no handlers.

05:47.200 --> 05:49.330
So the program jumps out of this scope.

05:49.330 --> 05:54.970
It returns from get_file() and it will now be inside this try block. And then it will look for the next

05:55.060 --> 05:56.980
catch handler up, which is this one.

05:57.580 --> 05:58.840
So it should get handled here.

05:59.950 --> 06:01.690
And here is some slightly different code.

06:02.080 --> 06:08.590
We have our vector access in a function, and then we have a main() function, which calls this inside

06:08.590 --> 06:09.610
a try block.

06:12.740 --> 06:15.950
So this is going to throw an exception, which is not handled in this function.

06:16.940 --> 06:18.590
It is going to go back to the caller.

06:19.100 --> 06:21.830
And then this is inside a try block, which has a handler.

06:22.250 --> 06:23.330
So it should handle it here.

06:24.660 --> 06:30.120
And if for some reason we get an exception, which is not a class in the inheritance hierarchy, that is

06:30.120 --> 06:34.320
going to jump out of this scope into main(), and there is no handler there.

06:34.980 --> 06:37.950
So we have run out of road, and the program terminates.

06:40.980 --> 06:45.720
OK, so it was a member of the exception hierarchy, so it is caught by this catch block in main().

06:46.940 --> 06:47.610
And there we are.

06:48.060 --> 06:49.620
Okay, so that is it for this video.

06:49.950 --> 06:53.130
I will see you next time, but until then, keep coding!
