Pointers to member functions

Pointers to functions

C++ allow pointers to functions, this means you can pass a function as parameter.

This sounds so good but with what aim? Well there are so many answers much better than mine. In few words, this allow us to make general functions and, also, in order to reuse code.

The syntaxis is "simple", identical to the function but with brackets and the pointer:

int addition (int a, int b);
int subtraction (int a, int b);


int (*add) (int,int) = addition;
int (*sub) (int,int) = subtraction;

To do something go to make a apply function:

#include <iostream>

int apply (int a, int b, int (*func)(int,int)){
     return (*func)(a,b);
}

int main(){
     int (*add) (int,int) = addition;
     int (*sub) (int,int) = subtraction;
     
     std::cout << apply(4,4,add) << std::endl;
     std::cout << apply(2,2,sub) << std::endl;
}


I know what are you thinking, oh yupi, he have added two numbers, or mabye (I hope so), hmm pass a function as parameter, interesting.

In whichever manner, this is just an introduction and is not very interesant. So, let's see a more useful example; how to sort arrays with a quite simple form.

#include <iostream>
#include <algorithm>

int main(){
     int a[6] = { 1, 3, 4, 12, 2, -1};
     std::sort(a, a + 6);
     
     for(int i = 0;i<6;i++) 
         std::cout << a[i] << ", ";
}

Ta-dah!! 

Yes, easy, and in a certain case where we need the array sorted by pair and odds?

#include <iostream>
#include <algorithm>

bool isPair (int a, int b){
     return (a%2) == 0;
}
int main(){
     int a[13] = { 1,2,3,4,5,6,7,8,9,10,11,12,13};
     std::sort(a, a + 13, isPair);
     
     for(int i = 0;i<13;i++) 
         std::cout << a[i] << ", ";
     
}

Note certain details like the arguments of isPair.

Sort needs two arguments in order to sort, in this case, really we wouldn't use it but it's necessary. An in the case we need a sequence like: (10 8 6 4 2 1 3 5 7 9)

Simple:

bool mySequence (int a, int b){
    if( ((a%2) == 0) and ((b%2) == 0) )//both even
        return a>b;
    else if( ((a%2) != 0) and ((b%2) != 0) )//both odd
        return a<b; //right or left (pair)|(even)
    else if((a%2) == 0 and (b%2) != 0 )//a even, b odd
        return true;
    else
        return false;
}

Or simply decreasing:

bool decreasing (int a, int b){
        return a>b;
}

C++ got the library functional where we can find some operator classes. For exmple, last example, we may do it in this way:

std::sort(a, a + 13, std::greater<int>() );

Following on arrays and the pass of functions as arguments I'd like to glimpse the library numeric.
Sometimes, you need to sum a whole array and, indeed, it's easy to do. However, may become tired.

Now, I show you an easy way.

#include <iostream>
#include <algorithm>
#include <functional>
#include <numeric>

int myOperation(int a, int b){
     int aux = a*2 + b;
     std::cout << a << ", " << b << " = " << aux << std::endl;
     return aux;
}

//If we want to pass a class as parameter to these functions
//the class have to got implemented operator()
struct myclass { int operator() (int a,int b) { int aux = a*10 + b; std::cout << a << ", " << b << " = " << aux << std::endl; return aux; } } myobject; int main(){ int v[] = {10, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int v2[] = {10,10,10,10};//10^4 int v3[] = {1,2,3}; std::cout << std::accumulate(v, v + sizeof(v)/sizeof(v[0]), 0) 
               << std::endl;
     std::cout << std::accumulate(v2, v2 + sizeof(v2)/sizeof(v2[0]), 
                                  1,//initial value
                                  std::multiplies<int>() ) //function to use
               << std::endl;
     std::cout << std::accumulate(v3, v3 + sizeof(v3)/sizeof(v3[0]),
                                  0,
                                  myOperation ) 
               << std::endl;
     std::cout << std::accumulate(v3, v3 + sizeof(v3)/sizeof(v3[0]), 
                                  0, 
                                  myobject ) 
               << std::endl;
}

output:



64
10000
0, 1 = 1
1, 2 = 4
4, 3 = 11
11
0, 1 = 1
1, 2 = 12
12, 3 = 123
123


All this can get complex, then is a good idea to declare a typedef. For example, if we need arrays:

#include <iostream>
#include <algorithm>
typedef int (*Op)(int, int);

int addition(int a, int b) {
     return (a + b);
}
int subtraction (int a, int b){
     return (a - b);
}

int apply(int a, int b, Op func) {
     return (func)(a, b);
}

int main() {
     Op add = addition;
     Op members[2] = {addition, subtraction};
     
     std::cout << apply(4, 4, add) << std::endl;
     std::cout << apply(4, 4, members[1]) << std::endl;
}

There are more cases like classes, templates, structs, functionoids where this get even complex, and, in fact, I just wanted an introduccion.


Pointers to member functions


Coming soon!

No comments:

Post a Comment