Hello again! In this video, we are going to look at member function pointers. C++ allows us to define
pointers to member functions of classes. Using them is more complicated than with normal function pointers.
Pointers to non-member functions.
The member function pointers use different syntax, and we may also need to provide the object that they are
called on.
When you call a member function, you have to provide an object.
Normally the compiler will do that for you, if you are calling it directly. But if you are going through a pointer
then you may need to do that yourself.
Member function pointers cannot be called directly. Unlike function pointers, we have to explicitly
dereference them. And that means that member function pointers are not callable objects.
So let's say we have a class with a member function and we want to have a pointer to this member function.
The syntax for doing this is even worse than with normal function pointers,
because we have to give the name of the class as well.
So "pfunc" is a pointer to a member of "Test".
It takes int and const string ref, and returns void.
And then, to initialize this variable, we have to give it the address of the member function.
And the ampersand is compulsory here.
It is not optional, like it is with function pointers.
To call a member function pointer,
we first need an object. Then we need to get the pointer as a member of the object, the member function
pointer.
And then we dereference it.
So we are doing both the "dot" and the "star" operations. And there is actually a special operator for this, which
does both.
So that is how you call a pointer to member function,
when you have an object. If you have a pointer to an object, then you need to use the arrow operator for
the member access.
So there is an "arrow star" operator.
So that is an operator with three characters.
C++11 has some features which help us when we're working with member
function pointers. First of all, the auto keyword, so we can just initialize the pointer with
the address, and let the compiler work out what the type is.
And we can also use type aliases.
So if we want to create a vector, for example, of member function pointers, we can create a type alias
and then use that.
So that makes the code look a lot cleaner.
So let's try this out.
We have our class with the member function.
We define a pointer to this member function. Or there is the C++11 syntax. And then we call the
member function through the pointer.
And there we are.
C++11 has a function called mem_fn() in the header, and this can be used to convert a member function
pointer into a callable object.
So we pass our member function pointer as an argument to mem_fn(), and this will return a callable object.
When we invoke this callable, we need to pass an object for the function to be called on.
So we need to give an object of the class as the first argument.
And then we give the arguments to the member function call.
So, the same member function again.
We use the C++11 syntax this time.
Then we called mem_fn(). We get our callable object.
And then we invoke it with an object of the class as the first argument.
We can also use bind() with member function pointers.
So let's go back to the example
in the last video. We had a vector of strings, and we were counting the number of cats in that vector.
So we have a class with a member function, which will do the match() function.
Then we use bind(), with the pointer to this member function as the first argument.
Then we have the address of a object of this class as the second argument.
Then we have a placeholder. That is going to be one of the strings from the vector.
That will be the first argument to this match() call.
And then we bind "cat" as the second argument to
that match() call.
So here is our code again.
We have the same count_strings() function, with the function object as argument.
We have our vector of strings, again.
We have this class, the same as the one on the slide, which will do the comparison.
And then we have our call to bind().
So this is going to return a callable object.
It will call the match() member function on this object, with "cat" as the second argument, and a first
argument which will be provided by the caller.
And then we pass that as the argument to count_strings().
So count_string() will iterate through the vector, and it will call this member function, with each element
of the vector as the first argument.
And there we are.
So when would you use member function pointers?
I have to admit the only time I have ever used them, is in concurrency. In C++,
with threads, you have to put the code for the thread inside a function, and then create a thread object
which has the address of that function.
If you're writing a class which has member functions which run in their own thread, that means you need to pass
member function pointers as arguments to the thread constructor.
You could also use member function pointers for making decisions at runtime.
You could have several objects of the same class, and then you decide which object has the member function
called.
So, for that, you would use bind(). You would bind the arguments to a member function call. You would leave the
object as a placeholder. And then, later on, someone will call this bound function.
They will provide the object they want, and that will call the member function with the arguments.
Or, alternatively, you could have a container of member function pointers, and then you decide which one
of these member functions gets called.
And in both cases, you can use a switch statement, or some if-else branches, to make the actual decision.
So you could use that for implementing state machines, callbacks and so on.
Okay, so that is it for this video.
I will see you next time.
But until then, keep coding!