WEBVTT

00:00.120 --> 00:04.290
Hello again! In this video, we are going to start looking at exceptions in C++.

00:04.860 --> 00:09.960
We are going to start off by looking at an example of an exception which is thrown by the standard library.

00:11.610 --> 00:14.490
This does not actually happen as often as you might expect.

00:14.910 --> 00:19.950
The reason is that the standard library has to work with every environment, including ones which do

00:19.950 --> 00:21.330
not support exceptions.

00:21.960 --> 00:25.500
So when it does throws exceptions, it is usually in something where you can avoid it.

00:27.570 --> 00:31.740
As an example, if we have a vector and we use subscript access.

00:32.900 --> 00:35.510
This will not perform any range checking.

00:35.990 --> 00:40.980
The idea is that you should know if the elements is in the vector or not.

00:41.270 --> 00:45.830
So there is no point wasting time checking. If you do access an element which is out of bounds,

00:46.220 --> 00:48.950
Then there is no warning, no error condition.

00:49.310 --> 00:52.460
The program will carry on, and probably crash or behave strangely.

00:53.060 --> 00:59.240
I'm actually going to use GNU C++ for my examples in this video, because the output is more useful for

00:59.240 --> 00:59.960
my purposes.

01:06.110 --> 01:06.740
So there we are.

01:06.860 --> 01:10.820
Segmentation fault, which is Unix's way of saying the program crashed.

01:18.130 --> 01:24.550
There is also a member function called at(), which does perform range checking. This will check its arguments

01:24.550 --> 01:25.450
at run time.

01:25.780 --> 01:30.010
And if that is not a valid index, it is going to create an exception object.

01:31.390 --> 01:34.580
As you can see, we are not actually doing anything to handle this exception object.

01:34.600 --> 01:36.280
So, what do you think will happen?

01:38.540 --> 01:40.430
And the answer is, the program should terminate.

01:41.210 --> 01:42.260
So let's see what happens.

01:48.890 --> 01:50.660
OK, so the program does terminate.

01:51.050 --> 01:56.780
It has called the library's terminate() function, which does what its name says. It has thrown an instance,

01:56.780 --> 01:58.910
or an object, of "out_of_range".

01:59.390 --> 02:00.140
So what is that?

02:00.740 --> 02:03.200
And there is also some output, which we will come back to in a minute.

02:05.820 --> 02:11.280
In C++, you are actually allowed to use any type you want for an exception object, including built-in

02:11.280 --> 02:15.060
types and your own types. That got rather confusing.

02:15.060 --> 02:19.950
So in C++ 98, they provided a standard exception class for the language.

02:21.040 --> 02:24.280
This gives a consistent interface for exception objects.

02:24.880 --> 02:27.700
It is actually the base class of an inheritance hierarchy.

02:28.120 --> 02:34.090
So this is one of the very few examples of where the library uses inheritance polymorphism.

02:37.860 --> 02:43.650
This exception class has a number of subclasses, which includes the "out_of_range" that we just saw.

02:44.430 --> 02:47.310
It also has a virtual member function, called what().

02:47.940 --> 02:53.580
And this will return a string, a C-style string, which describes the error condition.

02:55.020 --> 02:58.710
So if we go back to our output, it actually called what().

02:59.340 --> 03:00.660
And the string is a bit..

03:02.420 --> 03:08.340
jargonish, but you can see there is a range check of something which is two, and the size is zero.

03:08.870 --> 03:10.250
So that is why things went wrong.

03:16.730 --> 03:22.670
Let's try now to rewrite our example, so the exception is handled and the program will continue gracefully,

03:23.000 --> 03:29.090
instead of being terminated. The compiler will actually do most of the work for us, but we need to tell

03:29.090 --> 03:31.040
the compiler that we want the extra code.

03:33.430 --> 03:38.770
To do this, we take the code, which is likely to have a run-time error, and we put that inside its

03:38.770 --> 03:43.660
own block again, and we put the "try" key word in front of this block.

03:44.140 --> 03:45.310
So this will make the compiler

03:45.310 --> 03:47.410
generate the necessary code.

03:50.420 --> 03:56.990
Then for the handler, we have another block with the catch key word in front of it. After the catch

03:56.990 --> 04:01.070
key word, we put some round brackets with the type of the exception.

04:01.460 --> 04:04.850
So this is a bit like a function argument, although not exactly the same.

04:05.870 --> 04:10.280
If we put the base class in here, the exception, this will handle any subclass

04:10.280 --> 04:16.310
of that exception class. If we catch it by reference, then dynamic bining will be used.

04:16.760 --> 04:21.200
And if we call the what() member function, we will get the correct version for the subclass.

04:23.720 --> 04:24.770
So let's try that out.

04:24.980 --> 04:26.120
We have our vector again.

04:26.600 --> 04:29.210
We have our access inside of the try block.

04:30.360 --> 04:33.720
And then we have the exception handler, which follows straight after the try block.

04:34.710 --> 04:38.430
So we are going to catch the exception, and its subclasses, by reference.

04:39.330 --> 04:45.420
And in our handler, we are just going print out that we have an exception and then call the what() member

04:45.420 --> 04:45.870
function.

04:54.890 --> 04:59.780
So there we are. We get the "exception caught", and then we get the string returned by what().

05:05.500 --> 05:07.870
If we catch it by value, what do you think will happen?

05:13.260 --> 05:16.140
If we catch it by value, then static binding is going to be used.

05:16.590 --> 05:21.330
So the result of calling what() will be to call the exception class version.

05:25.570 --> 05:31.330
And there we are. So, "exception caught". And the exception version of what() just says this is an exception.

05:32.200 --> 05:36.910
So normally, you put the catch block straight after the try block, to catch the exceptions which are

05:36.910 --> 05:37.570
thrown in there.

05:38.560 --> 05:42.370
What happens if the catch block does not handle that particular exception.

05:43.510 --> 05:46.890
In that case, the program will jump out of the enclosing scope.

05:46.900 --> 05:49.870
So if we are in a function, it is going to return to the caller.

05:52.990 --> 05:57.710
Then it is going to look in the caller for a suitable catch handler, and if there is no suitable, it

05:57.940 --> 05:59.890
is going to go to the caller's, caller, and so on.

06:00.460 --> 06:03.900
Eventually, it will get to the main function and there is nothing to do.

06:03.940 --> 06:05.200
So the program will terminate.

06:06.310 --> 06:07.810
Okay, so that is it for this video.

06:08.050 --> 06:08.890
I will see you next time.

06:08.890 --> 06:10.960
But until then, keep coding!
