C++ basic introductory tutorial (9) : function pointer callback

  • 2020-04-02 02:58:53
  • OfStack

In Java, it is very simple to implement calling a piece of code at a certain time, and that is to use interfaces.
In C++, there is a more sophisticated way to use function Pointers.

For example, the timer (schedule) and message subscription (NotificationCenter) of cocos2d-x all use the function pointer to complete the callback function.
That's why we can always pass in a function as an argument, and at some point that function will be called.

The address of the function

It's easy to get the address of an int, such as int num; So the address of num is going to be &num.
While it is easier to get the address of the function, the name of the function is the address of the function, as follows:


void hello();
int _tmain(int argc, _TCHAR* argv[])
{
    auto p = hello;
    p();
    return 0;
}
void hello()
{
    cout << "helloworld";
}

We define a hello function and assign the function name directly to the pointer p, so we can use p as a hello function.
That's easy.

Declare function Pointers

Getting the address of a function is easy, but declaring a function pointer is not.
We can't always use auto to escape, can we? Sometimes we have to declare function Pointers explicitly, so how?
Remember what we said about typedefs defining type aliases? The same rule applies to the declaration of function Pointers. First declare a function, such as: void hello();
Then replace the function name with a pointer, such as: void (*p)();

Yeah, it's that simple, void of *p (); Is void the hello (); That's a statement.
Let's try it again right now. Int getValue(float dt);
What is its function pointer declaration? Int (*p) getValue(float dt);

Yeah, it's that simple int getValue(float dt); Int of p, getValue of float dt; The function pointer is declared.
Try again at once, this.. (xiao ruo: stop ~! Don't think you can screw around just because I'm not here!

Okay, so instead of trying, let's see, that code could go like this:


void hello();
int _tmain(int argc, _TCHAR* argv[])
{
    void (*p)();
    p = hello;
    p();
    (*p)(); //I added the sentence
    return 0;
}
void hello()
{
    cout << "helloworld";
}

Ok, very simple, not much to say ~
By the way, did you notice that I added another code on the sly?
That's right, it's (*p)(); Is also able to successfully call the hello function, why?

Third, historical reasons

Since p is the pointer, it points to the address of the hello function, so *p is the hello function, so *p () is equal to hello(), which is normal logic.
So, in fact, (*p)() is the more normal way to call.
 
However, since the function name is a pointer to the function, that is, hello is actually a pointer to the function's address.
In other words, p and hello are Pointers, so p and hello should be called the same way, so p() is the same as hello().
 
Both of these approaches are correct. In fact, grammar is determined by human beings. In history, predecessors held different views on these two approaches, so they tolerated the existence of these two seemingly conflicting approaches at the same time.
 
But I think most people would prefer to use p() instead of (*p)().

Iv. Typedef rescues complex function Pointers

The following code:


string hehe1(int num, float value);
string hehe2(int num, float value);
string hehe3(int num, float value); int _tmain(int argc, _TCHAR* argv[])
{
   
    string(*p[3])(int num, float value) = {hehe1, hehe2, hehe3};     string result = p[1](1, 2);
    cout << result.c_str() << endl;
    return 0;
} string hehe1(int num, float value)
{
    return "haha1";
}
string hehe2(int num, float value)
{
    return "haha2";
}
string hehe3(int num, float value)
{
    return "haha3";
}

This code has three functions with the same arguments and return values: hehe1, hehe2, and hehe3
Then, we will declare an array that will hold the three function Pointers.
The function here is relatively simple, so it doesn't look too complicated.
But it would be disheartening if there were too many such statements.

So the typedef saves us, and we can complicate the declaration by saying:


int _tmain(int argc, _TCHAR* argv[])
{
   
    typedef string(*HeheFunc)(int num, float value);
   
    HeheFunc p[3] = { hehe1, hehe2, hehe3 };
    string result = p[1](1, 2);
    cout << result.c_str() << endl;
    return 0;
}

After using a typedef instead of a function declaration, we can use it easily and make our representatives easy to understand.
Now, HeheFunc is a type. What type? This is the function type with an argument of (int num, float value) and a return value of string.

Five, the end

Okay, so much for the chatter.


Related articles: