WEBVTT

00:00.210 --> 00:07.560
Hello again! In this video, we are going to look at function pointers. The executable code for a function,

00:07.890 --> 00:14.580
the code that gets run when the function is called, is stored in memory. And we can actually guess a pointer

00:14.580 --> 00:15.990
to that code.

00:16.830 --> 00:23.100
We can take the address of the function, and then that will be a pointer to the start of that code.

00:24.660 --> 00:27.120
The actual type of this pointer is rather ugly!

00:29.370 --> 00:34.890
So it is declared as a pointer. Because of the operator precedence rules in C++, we have to put it inside

00:34.890 --> 00:36.730
brackets. Without the brackets,

00:36.750 --> 00:43.470
this would be interpreted as a function that returns pointer to void. With the asterisk inside the brackets,

00:43.620 --> 00:48.530
so points to a function, and this function takes two ints and returns void.

00:52.110 --> 00:57.730
So that is a pointer to the function. Generally, working with function pointer types is pretty ugly.

00:57.750 --> 01:02.700
We can avoid it in the declaration by using auto, but you need it in other places as well.

01:03.210 --> 01:06.000
So it is a good idea to use a type alias.

01:06.270 --> 01:08.400
So this is where the "using" keyword comes in.

01:09.150 --> 01:15.450
So we have "using" and then the alternative name, "pfunc", equals, and then we have the type.

01:15.930 --> 01:18.270
So this is without the variable name.

01:18.390 --> 01:21.690
So this is a pointer to a function which takes two ints and returns void.

01:27.240 --> 01:30.780
A function pointer is something called a callable object.

01:31.260 --> 01:35.340
So this is something that behaves like a variable, but it can be called like a function.

01:35.640 --> 01:38.460
So it is a kind of hybrid between data and code.

01:39.030 --> 01:44.940
We can copy it, we can pass it around, but we can also put a couple of buckets after it and call

01:44.940 --> 01:45.450
a function.

01:47.300 --> 01:51.170
And to do that, we just dereference the pointer. Again, we need the brackets.

01:51.680 --> 01:54.680
And then we put a couple of brackets, with the arguments inside.

01:56.910 --> 02:02.640
This means that a function pointer is what is called a "first-class object". So we can pass it as an argument

02:02.640 --> 02:07.080
to another function call and we can return it from another function call.

02:08.580 --> 02:10.170
So here is some code.

02:10.530 --> 02:15.390
We have a function which just adds the arguments together and prints out their sum.

02:15.660 --> 02:16.710
Nothing terribly exciting.

02:17.640 --> 02:19.860
We get a pointer to this function.

02:21.390 --> 02:26.730
In fact, you can miss out the ampersand. And then we call the function through the pointer by dereferencing

02:26.730 --> 02:27.270
the pointer.

02:28.290 --> 02:29.880
And again, the asterisk is optional.

02:30.240 --> 02:32.610
I prefer to leave the all in for consistency.

02:32.880 --> 02:38.400
The reason is that, when you return a pointer from a function, the asterisk is not optional. And it looks

02:38.400 --> 02:41.670
better if you have the asterisks and stars in, I think.

02:41.910 --> 02:43.200
But that is just a question of style.

02:43.980 --> 02:46.740
So this is going to call the function with arguments 1 and 2.

02:47.130 --> 02:51.360
So we should see "1 + 2 = 3", and indeed we do get that.

02:53.790 --> 02:59.880
To pass a function pointer as an argument, we just put the type in the function declaration. And then

02:59.880 --> 03:02.550
we put the type and the argument's name in the definition.

03:03.030 --> 03:10.560
So this is some function which takes two ints and a pointer too, pfunc, and then in the body of the function

03:10.560 --> 03:11.640
you can call the function.

03:12.180 --> 03:15.720
You can call it with the function arguments or some other arguments, if you wish.

03:18.210 --> 03:21.240
And also, we can return a function pointer from a function call.

03:25.100 --> 03:30.130
So this is basically the same code again, except we go through functions to return the function call.

03:30.740 --> 03:36.020
So this is basically the same code again, except we have a bit more indirection. So we have the same

03:36.110 --> 03:36.830
function again.

03:38.120 --> 03:42.320
There is an alias for it. And the asterisk is not optional in here!

03:43.340 --> 03:46.730
If you prefer the older C++ typedef, you can use that instead.

03:48.320 --> 03:52.760
Then we have a function which will take the function pointer as an arguument and call the function.

03:53.810 --> 03:55.220
Again, the asterisk is optional.

03:57.230 --> 04:02.250
We have another function which will return a function pointer. Actually, let's put the ampersand in

04:02.380 --> 04:02.630
there.

04:05.030 --> 04:08.510
So this will return a pointer to the function up here.

04:10.200 --> 04:18.720
That will be returned there. And then, in the main function we use that return value as the argument to the

04:19.230 --> 04:22.290
some_func here, which will call the function up here.

04:22.950 --> 04:26.310
So it is all a bit convoluted. But it is just to show you how the syntax works, really.

04:30.290 --> 04:31.670
And then we get the same result again.

04:35.320 --> 04:40.810
Function points were inherited from C, so they are pretty basic, and they have some drawbacks.

04:41.980 --> 04:45.910
The main use for function pointers is for writing what are called "callbacks".

04:46.750 --> 04:53.470
If you are calling a function from a GUI, or an operating system API, or framework, or some event

04:53.470 --> 04:59.500
driven code, quite often there is an argument which is a function pointer. And you can provide a function

04:59.500 --> 05:02.050
there, which will do something when something happens.

05:03.070 --> 05:07.750
So you can say that you want the operating system or the GUI to call this function if a particular

05:07.750 --> 05:08.530
event happens.

05:08.890 --> 05:14.010
For example, if the user clicks on a button, you can ask them to call this function, which will open

05:14.010 --> 05:15.910
a new window. Something like that.

05:17.200 --> 05:23.680
These are raw pointers. They can be overwritten by another function of the same type.

05:24.400 --> 05:27.070
They can be set to null and they can be uninitialized.

05:27.580 --> 05:29.860
So there's quite a bit of scope for problems here.

05:29.950 --> 05:34.840
Fortunately, they don't involve memory management! And also the syntax is pretty horrible.

05:35.470 --> 05:38.650
So there are better ways of doing this, and we'll look at those later on in the course.

05:40.000 --> 05:41.260
Okay, so that is it for this video.

05:41.770 --> 05:42.610
I will see you next time.

05:42.610 --> 05:44.770
But until then, keep coding!
