In the C ++ programming language, many functions are connected with the C language, such as pointer applications. Here we will introduce a C ++ function object similar to a function pointer. The C ++ function object is not a function pointer. However, in the program code, it is called in the same way as the function pointer, followed by a bracket. This is an entry-level article about the definition, usage, and relationship with function pointers and member function pointers of function objects.
The C ++ function object is essentially a class that implements the operator () -- parentheses operator. For example:
- Class Add
- {
- Public:
- Int operator () (int a, int B)
- {
- Return a + B;
- }
- };
- Add add; // define a function object
- Cout <add (3, 2); // 5
The function pointer version is:
- int AddFunc(int a, int b)
- {
- return a + b;
- }
- typedef int (*Add) (int a, int b);
- Add add = &AddFunc;
- cout << add(3,2); // 5
The usage is the same except for the definition method. All are:
- cout << add(3,2);
Since the usage of C ++ function objects and function pointers is no different, why should we use function objects? It's easy. Function objects can carry additional data, but pointers won't work. The following is an example of using additional data:
- class less
- {
- public:
- less(int num):n(num){}
- bool operator()(int value)
- {
- return value < n;
- }
- private:
- int n;
- };
When using:
- Less isLess (10 );
- Cout <isLess (9) <"" <isLess (12); // output 1 0
In this example, it seems to be too fun:
- Const int SIZE = 5;
- Int array [SIZE] = {50, 30, 9, 7, 20 };
- // Locate the first number smaller than the array and smaller than 10
- Int * pa = std: find_if (array, array + SIZE, less (10 ));
// Position where pa points to 9
- // Locate the first number smaller than the array and smaller than 40
- Int * pb = std: find_if (array, array + SIZE, less (40 ));
// Point pb TO 30
The convenience of C ++ function objects can be seen here? The advantage of function objects is that additional data can be stored in function objects.
Its weakness is also obvious. Although it is used as a function pointer, it is not a real function pointer after all. In the use of function pointers, it is powerless. For example, you cannot pass the function object to the qsort function! Because it only accepts function pointers.
To make a function accept both function pointers and function objects, the most convenient method is to use a template. For example:
- template<typename FUNC>
- int count_n(int* array, int size, FUNC func)
- {
- int count = 0;
- for(int i = 0; i < size; ++i)
- if(func(array[i]))
- count ++;
- return count;
- }
This function can count the number of qualified data in the array, for example:
- Const int SIZE = 5;
- Int array [SIZE] = {50, 30, 9, 7, 20 };
- Cout <count_n (array, SIZE, less (10); // 2
- There is no problem with using function pointers:
- Bool less10 (int v)
- {
- Return v <10;
- }
- Cout <count_n (array, SIZE, less10); // 2
In addition, a function pointer exclusive to the C ++ function object can be used to encapsulate class member function pointers! Because the function object can carry additional data, and the member function pointer lacks a Class Object (class instance) pointer for calling, you can save the class object pointer to the function object, you can call the corresponding class Object member function.
- Template <typename O>
- Class memfun
- {
- Public:
- Memfun (void (O: * f) (const char *), O * o): pFunc (f), pObj (o ){}
- Void operator () (const char * name)
- {
- (PObj-> * pFunc) (name );
- }
- Private:
- Void (O: * pFunc) (const char *);
- O * pObj;
- };
- Class
- {
- Public:
- Void doIt (const char * name)
- {Cout <"Hello" <name <"! ";}
- };
- A;
- Memfun <A> call (& A: doIt, & a); // save a: doIt pointer for calling
- Call ("Kitty"); // output Hello Kitty!
Now, the member function pointer can be easily saved for future calls.
- C ++ constant reference correct application method
- Interpretation of c ++ stack template application code
- Common application skills of C ++ clipboard
- C ++ Doxygen implementation function sharing
- How to format C ++ sprintf
However, the reality is cruel. Although a function object can store member function pointers and call information for calling like a function pointer, it has limited capabilities. A function object is defined, only one member function pointer with a specified number of parameters can be implemented.
Mem_fun in the standard library is such a function object, but it can only support 0 and 1 parameter member function pointers. For example, int A: func () or void A: func (int), int A: func (double), and so on. To add another parameter, such as: int :: func (int, double), sorry, not supported. If you want it, you only need to write it yourself.
What's more, how many can we write? Five? 10? Or 100 )?
Fortunately, the boost Library provides the boost: function class, which supports 10 parameters by default, and supports up to 50 function parameters (more). Generally, this is enough. However, its implementation is terrible: with some special and macro definitions of the template, dozens of template parameters are obtained, and dozens of function objects are biased (during compilation.
A proposal accepted by C ++ 0x is a list of variable template parameters. With this technology, you do not need to specialize in countless C ++ function objects. You only need a function object template to solve the problem.