C-Language callback functions and this pointer detail

Source: Internet
Author: User
Tags object model

In C, you often need to provide a function address, register into the structure, and then callback the function when the program executes to a specific stage. Creating a thread, the main function of the registered thread running is a typical example. Here is a simple callback instance that describes the problem with the this pointer when a callback function in C + + is a member function. C + + does not have its own thread encapsulation technology, as it is generally used to create threads, or C's callback function mechanism. There are a number of similar examples. In the pure object-oriented language such as Java, it is not the same, not only their own independent thread type, for callbacks, but also register the entire object, rather than registering a method, such as the common observer pattern. Here, a lot of information on this pointer, class member functions and static member functions of the relevant knowledge points, combined with their own understanding to make some summary.

With regard to the callback function, the member function of the class as the callback function, in general, we have formed the programming paradigm, discuss some uncommon usage, may be considered to be decadent, worthless. This is just an objective analysis of the technical points, thought may be encountered in similar scenarios and can not be sure.

Usually we understand that the member functions and this pointer are:

When you refer to a member function in the Drill-down C + + object model, when the member function is not static, a virtual function, then we have the following conclusions:

(1) & Class Name:: The function name gets the actual address of the member function;

(2) for function X, the obj.x () compiler is transformed into X (&obj), and &obj is passed as the this pointer;

(3) It is not possible to convert an effective conversion between a class member function pointer and a common function pointer of the same shape by forcing a type conversion.

Usually we understand that the normal member function of a class has a hidden argument, the first argument, whose value is this. If you want a member function to be able to access both the data member of the class and the callback function, there are several ways:

1. Static member functions as callback functions

For the sake of encapsulation, you can declare a function that needs to be a callback as static. A static member function that can be invoked directly outside of the class. We know that static member functions cannot directly access the Non-static data and interfaces of a class. Then you need to know the specific object address or reference to access the specific object members. There are two other ways to achieve this:

1 The address of the object is recorded with global variables, and the data members and methods are accessed through the global variable in the static member function. To see the specific code example:

#include <stdio.h>
#include <stdlib.h>

typedef void (*FUNC) (void*);

Class CallBack;
Class Callbacktest;

callback* g_obj = NULL;
callbacktest* g_test = NULL;

Class Callbacktest
{
Public
Callbacktest ()
{
M_fptr = NULL;
M_arg = NULL;
}

~callbacktest ()
{

}

void Registerproc (func fptr, void* arg = NULL)
{
M_fptr = fptr;
if (Arg!= NULL)
{
M_arg = arg;
}
}

void DoCallback ()
{
M_fptr (M_ARG);
}

Private
Func m_fptr;
void* M_arg;

};

Class CallBack
{
Public
CallBack (callbacktest* t): A (2)
{
if (t)
{
T->registerproc ((func) display);
}
}

~callback ()
{

}

static void Display (void* p)
{
if (g_obj)
{
g_obj->a++;
printf ("A is:%d", g_obj->a);
}
}

Private
int A;

};

int main (int argc, char** argv)
{
G_test = new Callbacktest ();
G_obj = new CallBack (g_test);
G_test->docallback ();

return 0;
}
Implement a callback to the callback member function, as shown on the code. Registers a static member function into the Callbacktest class in the constructor of the callback class. If the code is slightly this well, you can put the g_obj variable inside the callback class as a static member, which is even better. More elegantly, it would be better to pass the G_obj as a display parameter. So it's our usual practice to declare a member function as static, with an argument, as the object pointer to the class in which it is located, so that we can pass the this pointer to a static member function when we register, and use it as if the static member function has the this pointer.

#include <stdio.h>
#include <stdlib.h>

typedef void (*FUNC) (void*);

Class CallBack;
Class Callbacktest;

Class Callbacktest
{
Public
Callbacktest ()
{

}

~callbacktest ()
{

}

void Registerproc (func fptr, void* arg = NULL)
{
M_fptr = fptr;
if (Arg!= NULL)
{
M_arg = arg;
}
}

void DoCallback ()
{
M_fptr (M_ARG);
}

Private
Func m_fptr;
void* M_arg;

};

Class CallBack
{
Public
CallBack (callbacktest* t): A (2)
{
if (t)
{
T->registerproc ((func) display, this);
}
}

~callback ()
{

}

static void display (void* _this = NULL)
{
if (!_this)
{
Return
}
callback* pc = (callback*) _this;
pc->a++;
printf ("A is:%d", pc->a);
}

Private
int A;

};

int main (int argc, char** argv)
{
callbacktest* CBT = new Callbacktest ();
callback* cb = new CallBack (CBT);
Cbt->docallback ();

return 0;
}
The most common and orthodox solution, with the help of static member functions for the visibility of class data members, can be easily exploited:

pc->a++;
printf ("A is:%d", pc->a);
Such a statement to manipulate the member functions and member data of a class. However, it is still not possible to manipulate the member functions of a class directly using the hidden this pointer as a normal member function. There must be a lot of "good" students who want to access the members of a class directly like ordinary member functions. The next step is to explore this approach.

2. Non-static member functions as callback functions

Now that we know that a non-static member function has a hidden argument, if you can register it, pass in one more argument, and then the hidden argument to the object defaults to the value of this pointer, which is equivalent to assigning this to this when called. Can do a try, the code is as follows:

#include <stdio.h>
#include <stdlib.h>

typedef void (*FUNC) (void*);

Class CallBack;
Class Callbacktest;

Class Callbacktest
{
Public
Callbacktest ()
{

}

~callbacktest ()
{

}

void Registerproc (func fptr, void* arg = NULL)
{
M_fptr = fptr;
if (Arg!= NULL)
{
M_arg = arg;
}
}

void DoCallback ()
{
M_fptr (M_ARG);
}

Private
Func m_fptr;
void* M_arg;

};

Class CallBack
{
Public
CallBack (callbacktest* t): A (2)
{
if (t)
{
T->registerproc ((func) display, this);
}
}

~callback ()
{

}

void display ()
{
a++;
printf ("A is:%d", a);
}

Private
int A;

};

int main (int argc, char** argv)
{
callbacktest* CBT = new Callbacktest ();
callback* cb = new CallBack (CBT);
Cbt->docallback ();

return 0;
}
The attempt failed, prompting a compilation error. In the Appendix's Reference [1], the author takes a more direct assignment to the pointer variable, avoids the problem of compiling errors, but still complains when the call is made. The this pointer is not simply passed in as the first argument in the function call, but it is understandable in the process of understanding the member function accessing the data, but the actual running process is not. In Quotations 1 and 2, some feasible methods are given, further looking, this is the thunk technology, due to the behavior of the platform and compiler is strongly related. The general idea is to first fill out the this pointer to a specified register or a specified place, and when the name of the member function is invoked, the jump is automatically based on the address value of the Register plus the offset. Here is not a detailed introduction, interested students can refer to the link.

Using static member functions plus parameters to pass in the this pointer should be said to be a relatively perfect solution at present. Without losing the encapsulation, but also lose ease of use.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.