About calling class member functions with pointers in C ++ (2)

Source: Internet
Author: User

The pointers in C language are flexible and convenient, but also error-prone. Many beginners of C language, and even the old birds of C language, are easily planted under the pointer of C language. But it is undeniable that the pointer position in the C language is extremely important. Perhaps it can be extreme: a c program without a pointer is not a real C program.
However, the pointer to C ++ often gives me a feeling of being stuck. C ++ has stricter static types than C, more emphasis on type security, and more emphasis on checking during compilation. Therefore, for pointers that are the easiest to use in C language, we cannot let go: pointers in C ++ are divided into data pointers, data member pointers, function pointers, and member function pointers, they cannot be converted to each other. In addition, the declaration formats of these pointers are different:

Data Pointer T *
Member Data Pointer T ::*
Function pointer R (*)(...)
Member function pointer R (T ::*)(...)

Although C ++ still has a universal pointer void *, it is an object to be approved and cannot be "omnipotent" anymore. It cannot be converted to a member pointer.

In this way, the C ++ pointer becomes very embarrassing: we need a pointer that can point to the same type of data, whether it is common data or member data; we need a pointer that can point to a function of the same type, whether it is a static function or a member function. But no, at least from the current C ++ standard.
 
Mu Feng wangzhi C ++ pointer (3) member function pointer

Since we had classes, we began to organize data structures by data + operations. Since we had templates, we began to separate data from algorithms for reuse, it's really tough. However, no matter how hard it is, most functions are no longer single, and they are married to the class and enter the besieged city. However, we still need to be able to freely call these member functions.
Consider scheduled calls in windows. The prototype of the settimer function is as follows:

Uint_ptr settimer (
Hwnd,
Uint_ptr nidevent,
Uint uelapse,
Timerproc lptimerfunc
);

The parameter is not explained. Most windows developers know this function. Lptimerfunc is a function pointer that will be called regularly. If we don't trigger a timer through the wm_timer message, but use lptimerfunc to work on a scheduled basis, we can only use common or static functions, but cannot use member functions in any case, not even through static function transfer.

Consider the thread creation: uintptr_t _ beginthread (
Void (* start_address) (void *),
Unsigned stack_size,
Void * Arglist
);

Start_address only supports common functions. But this time it is okay. It allows the callback function to have a void * parameter, which uses Arglist as the parameter to call start_address. As a result, the smart C ++ programmer uses Arglist to pass this pointer, so that the static function can be used to successfully call the member function: Class mythread
{
Public:
Static void doit (void * pthis)
{
(Mythread *) pthis)-> doit ();
}
Void doit (){}
};

Main ()
{

Mythread * PMT = new mythread;
_ Beginthread (& mythread: doit, 0, (void *) PMT );

}

But it is clear that C ++ programmers will not be satisfied with this. There are many unstable factors criticized by C ++. It uses C ++-considered unsafe type conversion, insecure void * pointer, and so on. However, this is The Calling Interface left by the system for the C language. So how can we call the member function pointer in the C ++ program?
For example, we plan to call the specified member functions for all classes in the vector:

# Include <vector>
# Include <algorithm>
# Include <functional>
# Include <iostream>
Using namespace STD;

Class
{
Int value;
Public:
A (INT v) {value = V ;}
Void doit () {cout <value <Endl ;};
Static void call_doit (A & rThis)
{
RThis. doit ();
}
};

Int main ()
{
Vector <A> Va;
Va. push_back (A (1 ));
Va. push_back (A (2 ));
Va. push_back (A (3 ));
Va. push_back (A (4 ));
// Method 1:
// For_each (va. Begin (), Va. End (), & A: doit); // Error
// Method 2:
For_each (va. Begin (), Va. End (), & A: call_doit );
// Method 3:
For_each (va. Begin (), Va. End (), mem_fun_ref <void, A> (& A: doit ));

System ("pause ");

Return 0;
}

Method 1: Compilation fails. For_each only allows function pointers or function objects with one parameter, even if a: doit has a default this pointer parameter. Not because for_each didn't take this into consideration, but it couldn't do it!
Method 2 is obviously inspired by beginthread. It is successful to use a static function for call. But it's not easy! This is not c ++.
Method 3: call. The member function pointer is finally packaged with mem_fun_ref.
It seems that method 3 is good, type-safe, and generic-slow. First of all, it is ugly. How can I call a common C function pointer so beautiful (see method 2 ), A large string of packaging, angle brackets and parentheses are also indispensable & No! Second, it can only wrap functions that do not exceed one parameter! Although it is enough in for_each, if you want to use more than one parameter, there is only one sentence: impossible tasks.

Yes. In Standard C ++, this is an impossible task. But things are not always pessimistic. At least many third-party libraries provide packaging that surpasses mem_fun. For example, boost: function. However, it also has limits: The supported parameters are still limited, and there are only a dozen or more parameters, even though they are enough for your use. Similarly, it is ugly, never think that it can be simply used.

Maybe, in exchange for quality assurance at the cost of losing the beauty, this is also a kind of helplessness of C ++ for function pointers ......

C ++ 0x is expected. It uses variable template parameters to enable unlimited mem_fun parameters ......

--------
BTW: C ++ builder extends a keyword closure, allowing member function pointers to be used as common function pointers. Maybe C ++ 0x can consider ......

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.