WEBVTT

00:01.890 --> 00:08.340
Hello again! In this video, we're going to look at casting. Casting means converting the type of

00:08.340 --> 00:09.030
an expression.

00:10.020 --> 00:15.600
The original form of casting, as used in C, was to convert an expression from one type to another.

00:16.680 --> 00:24.210
When const came along, which was actually in C++ but imported back into C, there was a lot of code still

00:24.210 --> 00:25.950
around that didn't use const.

00:26.160 --> 00:32.220
So any new code that used const had to be able to work with old code, so they needed some way of converting

00:32.220 --> 00:35.760
from const expressions to non-const expressions.

00:37.920 --> 00:43.290
If you're working at lower levels - perhaps you might have a data structure which contain this data with

00:43.290 --> 00:49.380
different types, and you want to send that data over a network which knows nothing about C++ types.

00:49.980 --> 00:55.080
Then you have to convert your data into a stream of binary data, which is a string of ones and zeros.

00:55.740 --> 00:57.660
So you need to cast that as well.

00:58.620 --> 01:03.030
And then finally, when you're working with inheritance, which we'll be looking at later on in the course,

01:03.660 --> 01:09.150
often you need to be able to convert a pointer to a base class into a pointer to a derived class.

01:10.290 --> 01:15.330
And you may be thinking these all sound a bit dubious. And you're correct,

01:15.330 --> 01:20.010
they are a bit dubious! If you're writing good C++ code.

01:20.340 --> 01:23.940
It's very rare that you should actually need to put an explicit cast in your code.

01:25.490 --> 01:28.520
If you do, it's often a sign that something suspicious is going on.

01:29.240 --> 01:35.570
I mean, you might need it occasionally to interact with code written in C or some other code in C++

01:35.570 --> 01:37.190
that's not been very well written.

01:37.730 --> 01:41.540
But generally, it's a warning sign that something funny is going on.

01:44.270 --> 01:50.300
The traditional way of casting is the way that it's done in C, which is to take the type that you once

01:50.720 --> 01:52.790
you put in brackets before the expression.

01:53.180 --> 01:56.390
So in this case, we're converting c to a character.

01:58.780 --> 02:04.750
So we have this character, stored in an int. Presumably it's been read from input because that's

02:04.750 --> 02:06.850
what the function call returns.

02:07.750 --> 02:12.840
If we print out this character, which is actually an int, we get the numeric value.

02:13.690 --> 02:17.320
But if we cast it to char, then we'll get the character.

02:20.070 --> 02:25.830
So there we are. When we print out the int we get 65, when we cast to character, we get the letter A,

02:26.070 --> 02:27.600
which is what we actually wanted.

02:28.560 --> 02:30.960
So that's the kind of thing that people used to do in C.

02:35.430 --> 02:42.720
When C++ was standardized, they decided to add some new cast operators, one for each type of cast.

02:43.500 --> 02:46.380
And they also provided a very distinctive syntax.

02:46.830 --> 02:52.080
So it stands out very clearly and there's no possibility of being in any doubt about what's happening.

02:52.800 --> 02:58.680
So instead of having type in brackets before the expression, we have something which says what kind

02:58.680 --> 03:02.510
of cast it is. Then the type is a template parameter,

03:02.520 --> 03:08.790
so it goes in angle brackets and then he puts the expression that you want to cast in round brackets.

03:09.480 --> 03:10.980
What's the reason for this syntax?

03:11.400 --> 03:12.420
Bjarne Stroustrup said,

03:12.600 --> 03:18.630
"An ugly operation should have an ugly syntactic form!" And he actually puts ugly in bold quotes, so

03:18.630 --> 03:22.590
he obviously feels really, really strongly about this.

03:24.490 --> 03:30.130
And he must have had some bad experiences. Which is not surprising, really, because casting turns off a lot of

03:30.130 --> 03:31.870
compiler checks which prevent bugs.

03:32.290 --> 03:36.790
So if you cast, you open yourself up to bugs that wouldn't normally occur.

03:43.110 --> 03:48.750
So for the code that we had before, we would use static cast, which just means changing the static type

03:48.750 --> 03:49.470
of the expression.

03:50.250 --> 03:55.020
So we would change c to a char using a static cast.

03:57.540 --> 04:05.310
So the code would look like this. We have this static_cast, we have character as the parameter and

04:05.310 --> 04:07.890
then we have the expression we want to cast in brackets.

04:09.210 --> 04:13.080
And then when we run this, we get the same result as before.

04:15.870 --> 04:19.860
The difference is there's no chance you could miss this when you're scanning through code, even if

04:19.860 --> 04:22.530
you're looking very quickly through hundreds or thousands of lines of code.

04:22.560 --> 04:23.310
You'll notice this.

04:23.790 --> 04:25.830
And also, it's very obvious what's happening.

04:26.490 --> 04:28.020
It's definitely a static cast.

04:28.050 --> 04:30.480
You don't have to stop and read the code to work out what it does.

04:35.790 --> 04:38.490
The second form of cast is the const cast.

04:38.820 --> 04:42.150
So this converts a const expression to the non-const equivalent.

04:42.540 --> 04:47.160
So if you have something that's not supposed to be changed, this allows you to change it, which is

04:47.160 --> 04:48.480
generally a bad thing to do.

04:52.080 --> 04:56.460
You may need this occasionally to call old or badly-written code that doesn't use const when it

04:56.460 --> 05:01.590
should, for example, in this function. We have a function that takes an argument.

05:02.760 --> 05:06.600
The function doesn't actually change the arguments, but the argument is not const.

05:07.720 --> 05:13.600
And then if we want to pass something that is const to this argument, we need to cast it to a non-const

05:13.970 --> 05:20.890
variable, which is a bit dubious. But it's actually okay in this case because print doesn't change

05:20.890 --> 05:21.640
the argument.

05:25.530 --> 05:32.640
So we'd use the const_cast. We would have char * as the argument, because that's what we want to convert

05:33.240 --> 05:36.180
the expression to. So it's originally a pointer to const char.

05:37.130 --> 05:40.580
And then the argument is the thing we want to cast.

05:40.910 --> 05:47.240
So this is going to take this expression, which is an array of const char or a pointer to const char,

05:47.900 --> 05:50.870
and it's going to pretend that it's actually non-const car.

05:54.230 --> 05:55.760
So it does work and print out

05:55.790 --> 05:56.360
Hello, world.

05:57.410 --> 06:02.300
And you may want to think about what happens if this function is changed and it does actually modify

06:02.300 --> 06:03.860
the string that's passed into it.

06:06.510 --> 06:11.430
What will happen is that you won't get a compiler error because you've told the compiler that you want

06:11.430 --> 06:12.060
this to be

06:13.010 --> 06:13.550
mutable.

06:14.940 --> 06:20.580
So you've turned off an important compiler check. It may well be that this is stored in memory, which

06:20.580 --> 06:24.630
is read only, because it's constant, so it's not going to be changed, of course.

06:25.230 --> 06:29.580
And then when this function does change it, you may well get a memory violation.

06:31.200 --> 06:32.520
So that's why that's a bad thing.

06:36.160 --> 06:39.880
So if print does mutates the arguments, then you get undefined behavior.

06:41.640 --> 06:46.110
And then very quickly looking at the other two, because they're a bit more advanced. reinterpret_cast

06:46.110 --> 06:49.560
is the one that will convert data to untyped binary data.

06:50.100 --> 06:54.810
And you'd mainly use that if you're doing low level work like communicating with hardware or the operating

06:54.810 --> 06:58.620
system, or producing a binary file or reading in a binary file.

06:59.100 --> 07:02.970
And we're actually going to look at how to work with binary files later on in the course.

07:04.700 --> 07:05.960
(I'm giving you all these teasers!)

07:08.500 --> 07:14.590
Then finally, dynamic_cast so this will convert a pointer to a base class object to a pointer to a derived

07:14.590 --> 07:15.310
class object.

07:16.240 --> 07:22.240
And it also works with references. And we'll talk about that later on when we go into polymorphism.

07:23.020 --> 07:24.760
And this is different from the other types.

07:25.030 --> 07:27.460
The other ones are all done by the compiler.

07:28.270 --> 07:30.940
This is actually code that gets executed at runtime.

07:31.240 --> 07:33.630
But again, we'll go into the details of that later on.

07:35.050 --> 07:36.880
Okay, so that's all for this video.

07:37.420 --> 07:38.380
I'll see you next time.

07:38.380 --> 07:40.600
But meanwhile, keep coding!
