WEBVTT

00:00.120 --> 00:04.440
Hello again! In this video, we are going to look at the subclasses of standard exception.

00:06.010 --> 00:11.800
So the immediate subclasses are bad_alloc, which is for memory allocation errors and bad_cast

00:11.800 --> 00:14.320
for when a dynamic cast fails.

00:15.280 --> 00:19.510
And then there are two sub-hierarchies, for logic errors and run-time errors.

00:22.710 --> 00:28.500
In the logic error hierarchy, we have out_of_range. So we have seen that with the at() member function of vector.

00:28.920 --> 00:35.700
This is thrown when we try to access an element outside the defined range. invalid_argument.

00:35.760 --> 00:40.770
So for example, stoi() takes a string and returns an int.

00:41.250 --> 00:47.160
But if the argument cannot be converted to a number, then the invalid_argument is thrown.

00:47.190 --> 00:50.010
So that is any case where the argument is not acceptable.

00:51.400 --> 00:52.150
domain_error.

00:52.480 --> 00:57.910
If we have something which takes a date, and we give some invalid date, like the 31st of February,

00:58.510 --> 01:01.390
then that is outside the domain of applicable values.

01:02.870 --> 01:09.170
And length_error. If we try to append too many elements to a string, then that will exceed the length limit of

01:09.170 --> 01:09.920
the object.

01:12.540 --> 01:19.200
For runtime_error, these are more numerical. overflow_error means that the result is too large for the

01:19.200 --> 01:19.650
variable.

01:20.010 --> 01:22.170
So there are too many digits to be stored.

01:23.240 --> 01:29.180
underflow_error means that the result of a floating-point computation is too small. There

01:29.180 --> 01:37.340
are too many zeros after the decimal points, before you get to the actual, non-zero digits. And then

01:37.340 --> 01:41.300
a range_error we have some intermediate result which cannot be represented.

01:44.250 --> 01:47.850
So you might think there are lots of places where the standard library could use exceptions.

01:49.560 --> 01:52.020
So here is an example with the square root function.

01:52.380 --> 01:54.840
This is from the <cmath> header.

01:55.950 --> 02:00.810
It has a precondition, which is that the argument must be a positive number.

02:01.530 --> 02:04.710
So if we call it with -1, we violate the precondition

02:04.710 --> 02:11.370
and we get a logic error. And -1 is outside the range of acceptable values, so we should get a

02:11.420 --> 02:15.240
domain_error exception, and that should get caught by this catch block.

02:16.050 --> 02:17.130
So let's see what happens.

02:19.200 --> 02:28.410
And we get this weird-looking result. minus nan brackets ind. So obviously, we did not get an exception.

02:28.770 --> 02:29.970
Otherwise, it would have been caught.

02:30.600 --> 02:37.350
So the function has actually completed and returned. And the value that it returned is "not a number".

02:38.070 --> 02:41.310
So this is something from the floating-point implementation.

02:41.820 --> 02:47.220
If you get something which cannot be represented as a floating point number, like dividing by 0

02:47.220 --> 02:53.880
or getting the square root of -1, then the result is NaN. "Not a number".

02:57.730 --> 03:01.360
By default, the C++ streams do not throw exceptions.

03:01.960 --> 03:07.810
I think the argument is, that it is very easy to check the stream's state. And if you want an exception,

03:07.810 --> 03:08.890
you can throw one yourself.

03:09.550 --> 03:12.850
But in C++11, you can actually enable exceptions.

03:14.970 --> 03:20.580
To do that, you need to call the exceptions() member function for the object, for the stream object, and

03:20.580 --> 03:24.960
then you need to say which error conditions you want to cause an exception.

03:25.500 --> 03:30.900
So in this case, if fail_bit or bad_bit is set, "ifile" is going to throw an exception.

03:35.800 --> 03:41.680
So let's try that out. We need to #include <ios> to get these input/output exceptions.

03:42.760 --> 03:46.510
We create a stream object, an input file stream.

03:47.260 --> 03:54.010
Then we enable exceptions, like we did on the slide. And then we have a try block, where we have an operation

03:54.100 --> 04:00.610
that might throw an exception. If this "txt" file is not available.

04:00.610 --> 04:06.010
If it does not exist or we are not allowed to access it, then this will throw an exception which should

04:06.010 --> 04:06.940
get caught here.

04:07.570 --> 04:08.560
So let's see what happens.

04:10.320 --> 04:11.950
Right, so we do get the exception.

04:12.460 --> 04:16.150
So this has thrown an exception because the file does not actually exist.

04:17.500 --> 04:21.610
The message is maybe not very user friendly, but it is there.

04:24.710 --> 04:28.760
So why does the C++ library avoid using exceptions so much?

04:29.420 --> 04:31.250
Well, the answer really is efficiency.

04:31.940 --> 04:38.120
The library has to work with every kind of application on every kind of hardware that supports C++.

04:38.960 --> 04:43.640
And if you are going to be checking for exceptions and handling them, then that will require extra

04:43.640 --> 04:46.910
code, and sometimes that may not be acceptable.

04:47.960 --> 04:53.360
For example, the square root function is already quite slow compared to doing basic arithmetic operations.

04:54.200 --> 04:57.410
If you are doing numeric programming, or games, or multimedia.

04:57.920 --> 05:02.900
Then having a square root which checks and throws exceptions could add too much overhead.

05:04.190 --> 05:09.560
However, there are third party libraries which use exceptions, and of course, we are allowed to use

05:09.560 --> 05:10.730
them in our own code.

05:11.690 --> 05:13.220
Okay, so that is it for this video.

05:13.640 --> 05:16.880
I will see you next time, but until then, keep coding!
