class member functions in C + + as callback functions __jquery

Source: Internet
Author: User

Reproduced from: http://blog.csdn.net/this_capslock/article/details/17001003

Callback functions are based on the C programming Windows SDK Technology, not for C + +, programmers can be a C function directly as a callback function, but if you try to directly use C + + member functions as a callback function will have errors, or even compile can not pass.

Ordinary C + + member functions imply a pass-through function as an argument, that is, the "This" pointer, which is implemented by passing a pointer to itself to its member function, thereby enabling the program function to access the data members of C + +. This also makes sense of why multiple instances of a C + + class can share member functions but do have different data members. Because the this pointer is used to install a member function of type callback as a callback function, a callback function installation fails because the implied this pointer causes the number of function parameters to not match.

In theory, a member function of a C + + class cannot be used as a callback function. But when we use C + + programming, we always want to implement its function in the class, that is, to maintain the encapsulation, if the callback function to write a common function has a lot of inconvenience. After searching and researching on the Internet, several ingenious methods have been found to make the class member function used as a callback function.

This uses the Linux C + + thread to create the function Pthread_create example, its prototype is as follows:

int pthread_create (pthread_t *restrict TIDP, const pthread_attr_t *restrict attr, void* (*START_RTN) (void*), void *res Trict Arg);  

The first parameter is a pointer to the thread identifier.
The second parameter is used to set the thread properties.
The third parameter is the starting address of the thread's running function, which is the callback function.
The last parameter is the parameter of the running function.

Here we only focus on the third parameter Start_run, which is a function pointer to a function that takes void* as the parameter and returns a value of void*, which is used as a thread's callback function, and executes the code of the function after the thread starts.

Method One: The callback function is a normal function, but the member function is executed in the body of the function

    Class MyClass  
    {  
        pthread_t TID;  
    Public:  
        void func ()  
        {  
            //child Thread Execution code  
        }  

        bool Startthread ()  
        {//start child thread  
            int ret = Pthread_create (&tid, NULL, callback, this);  
            if (Ret!= 0) return  
                false;  
            else return  
                true;  
        }  
    ;  

    Static void* callback (void* Arg)  
    {//callback function  
        ((myclass*) arg)->func (); Call member function return  
        NULL;  
    }  

    int main ()  
    {  
        MyClass A;  
        A.startthread ();  
    }  

class MyClass needs to carve out a child thread inside itself to execute code in the member function func (), which is started by calling the Startthread () member function. Here, the callback function, callback, is written outside the class, and the passed parameter is a pointer to the MyClass object (specified in Pthrad_create () by the 4th parameter this), and the callback function casts void* into myclass*, Then call Arg->func () to execute the code for the child thread.

The principle of this is to give the current object pointer as a parameter to an external function, and then by the external function call the class member function, with the external function as a callback function, but perform the function of member functions, which is equivalent to a layer of conversion in the middle. The disadvantage is that the callback function, outside of the class, affects encapsulation, where the callback () is limited to static to prevent calls to this function in other files.

Method Two: callback function is static member function inside class, call member function inside it
Make a little change on the method, and move the callback function to the class MyClass, which keeps the encapsulation. The code is as follows:

 class MyClass {static myclass* curmy;//storage callback function call object static void* CA  
        Llback (void*);//callback function pthread_t TID;  
            void Func () {//Child thread Execution Code} void Setcurmy () {//Set the object that the current object calls to the callback function  
        Curmy = this;  
            Public:bool Startthread () {//boot child thread setcurmy ();  
            int ret = pthread_create (&tid, NULL, myclass::callback, NULL);  
            if (Ret!= 0) return false;  
        else return true;  
    }  
    };  
    myclass* myclass::curmy = NULL;  
        void* Myclass::callback (void*) {curmy->func ();  
    return NULL;  
        int main () {MyClass A;  
    A.startthread (); }  

The class MyClass has 1 static data member Curmy and a static member function callback. Curmy is used to store a pointer to an object that acts as the parameter arg of the callback function in method one. Callback as a callback function, executing the code for the Curmy->func (). Call Setcurmy () before each thread is created to let the curmy point to the current self.

The benefits of this approach are well protected, MyClass exposes only one interface Startthread (), and the child-threading code and callback functions are both private and invisible to the outside world. In addition, there is no callback parameter, which can be transferred from the outside. However, before each object initiates a child thread, be sure to call Setcurmy () to let Curmy correctly point to itself, otherwise the thread will open for other objects, which can have serious consequences.

Method Three: Cast the member function as a callback function

    Class MyClass  
    {  
        pthread_t TID;  
        void func ()  
        {  
            //child Thread Execution code () public  
    :  
        bool Startthread () {//
            boot child thread  
            typedef void* (* FUNC) (void*); The FUNC type is a pointer to a function that is void*, the return value is void* FUNC callback  
            = (FUNC) &myclass::func;//cast FUNC ( The type  
            int ret = pthread_create (&tid, NULL, callback, this);  
            if (Ret!= 0) return  
                false;  
            else return  
                true;  
        }  
    ;  

    int main ()  
    {  
        MyClass A;  
        A.startthread ();  
    }  

This method is the principle that Myclass::func will eventually be converted into void func (MyClass this); This means inserting the this pointer to the object itself before the first argument. You can use this feature to write a Non-static class member method directly as a thread callback function. In the case of compilers, void (MyClass::* FUNC1) () and Void (FUNC) (void) These two function pointers, although they look very different, have the same final form, so you can cast the member function pointer as a pointer to a normal function as a callback function. When you create a thread, you pass the current object's pointer this as a parameter to the callback function (member function func) to know which object the thread is built against.

Method Three has better encapsulation than method two, because it does not involve the problem of sharing a static member with multiple objects, and each object can start its own thread independently without affecting other objects

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.