8

I am trying to grasp pointer function concept in a better way. So I have a very simple and working example as:

#include <iostream>

using namespace std;

int add(int first, int second)
{
    return first + second;
}

int subtract(int first, int second)
{
    return first - second;
}

int operation(int first, int second, int (*functocall)(int, int))
{
    return (*functocall)(first, second);
}

int main()
{
    int  a, b;
    int  (*plus)(int, int);
    int  (*minus)(int, int);
    plus = &add;
    minus = &subtract;
    a = operation(7, 5, add);
    b = operation(20, a, minus);
    cout << "a = " << a << " and b = " << b << endl;
    return 0;
}

So far so good, Now I need to group the functions in a class, and select add or subtract based on the function pointer that i use. So I just make a small modification as:

#include <iostream>

using namespace std;

class A
{
public:
int add(int first, int second)
{
    return first + second;
}

int subtract(int first, int second)
{
    return first - second;
}

int operation(int first, int second, int (*functocall)(int, int))
{
    return (*functocall)(first, second);
}
};

int main()
{
    int  a, b;
    A a_plus, a_minus;
    int (*plus)(int, int) = A::add;
    int (*minus)(int, int) = A::subtract;
    a = a_plus.operation(7, 5, plus);
    b = a_minus.operation(20, a, minus);
    cout << "a = " << a << " and b = " << b << endl;
    return 0;
}

and the obvious error is:

ptrFunc.cpp: In function ‘int main()’:
ptrFunc.cpp:87:29: error: invalid use of non-static member function ‘int A::add(int, int)’
ptrFunc.cpp:88:30: error: invalid use of non-static member function ‘int A::subtract(int, int)’

coz I haven't specified which object to invoke(and I don't want to use static methods for now)

EDIT: several comments and answers suggested that the non-static version(as I have written) is not possible.(thanks to all) So, Modifying the class in the following manner also wont work:

#include <iostream>

using namespace std;

class A
{
    int res;
public:
    A(int choice)
    {
        int (*plus)(int, int) = A::add;
        int (*minus)(int, int) = A::subtract;
        if(choice == 1)
            res = operation(7, 5, plus);
        if(choice == 2)
            res = operation(20, 2, minus);
        cout << "result of operation = " << res;
    }
int add(int first, int second)
{
    return first + second;
}

int subtract(int first, int second)
{
    return first - second;
}

int operation(int first, int second, int (*functocall)(int, int))
{
    return (*functocall)(first, second);
}
};

int main()
{
    int  a, b;
    A a_plus(1);
    A a_minus(2);
    return 0;
}

generated this error:

ptrFunc.cpp: In constructor ‘A::A(int)’:
ptrFunc.cpp:11:30: error: cannot convert ‘A::add’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’
ptrFunc.cpp:12:31: error: cannot convert ‘A::subtract’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’

may I know how to solve this issue please?

thanks

rahman
  • 4,820
  • 16
  • 52
  • 86

4 Answers4

7

The syntax to declare a function pointer to member methods is:

int (A::*plus)(int, int) = &A::add;
int (A::*minus)(int, int) = &A::subtract;

To invoke member methods use .* or ->* operator:

 (a_plus.*plus)(7, 5);

Also have a look at http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx

Hope this helps.

Complete code:

     #include <iostream>

    using namespace std;

    class A
    {
    public:
    int add(int first, int second)
    {
        return first + second;
    }

    int subtract(int first, int second)
    {
        return first - second;
    }

    int operation(int first, int second, int (A::*functocall)(int, int))
    {
        return (this->*functocall)(first, second);
    }
    };

    int main()
    {
        int  a, b;
        A a_plus, a_minus;
        int (A::*plus)(int, int) = &A::add;
        int (A::*minus)(int, int) = &A::subtract;
        a = a_plus.operation(7, 5, plus);
        b = a_minus.operation(20, a, minus);
        cout << "a = " << a << " and b = " << b << endl;
        return 0;
    }
Arun
  • 2,087
  • 2
  • 20
  • 33
  • 1
    adding & to declarations (regardless of invocation) will generate same errors. – rahman Apr 02 '13 at 05:11
  • How about my last code snippet. I tried to apply your solution to it. it doesn't work. can you check it out?(please) – rahman Apr 02 '13 at 05:26
  • Methods been declared as static, instead should be non-static and the signature and impln of "int operation(int first, int second, int (*functocall)(int, int))" should be changed. – Arun Apr 02 '13 at 05:31
  • ok.let me check. I am not sure you will be able to modify your code once I mark it as true. so I wait a bit before marking it true. thanks – rahman Apr 02 '13 at 05:33
  • In Ctor(), you have to use: " int (A::*plus)(int, int) = &A::add; int (A::*minus)(int, int) = &A::subtract; "and method as "int operation(int first, int second, int (A::*functocall)(int, int)) { return (this->*functocall)(first, second); }" – Arun Apr 02 '13 at 05:50
  • yeah, I got it working when I changed the signature of operation. Thanks Arun. I made it work with trial and error. I still have trouble understanding why I did that.I guess I must read the reference you sent me. Thanks again – rahman Apr 02 '13 at 05:56
  • C++ has got some cryptic syntax to handle function pointers to member methods. You'll get used to it eventually! :) – Arun Apr 02 '13 at 05:58
  • Why is "this->" required in the operation function? The function pointer already has the class specifier on it, shouldn't (*functocall)(params) or just functocall(params) work too? Why do you have to specify this. oh I see why, I just answered my own question, the function pointer doesn't supply the object, just the function. I get it. – stu Mar 02 '16 at 22:30
2

You can't pass non-static member function as argument that easy. And for your needs, I believe it's better to override operators: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/

But if you really need them as actual member functions - just make them static.

Wintermute
  • 1,501
  • 17
  • 22
  • no that is not what i need. I guess I didn't explained the problem clearly. I will just make some changes. If that also has no solution, please let me know. thanks. – rahman Apr 02 '13 at 05:01
  • 1
    After changes my answer still stands. As Alok Save pointed out, member functions still have implicit this as first parameter. New errors are generated are actually answering your question: (*)(int,int) declaration is not (A::)(int,int) - you must change declaration and dereference them appropriately. You should probably tell us reasons why you can't have them static or better yet have them as overriden operators, their logic just asks to make them static :) – Wintermute Apr 02 '13 at 05:15
2

The edit you made to your code is still wrong because it doesn't make the member functions static. You need to make the add, subtract etc. functions static by adding the static specifier:

#include <iostream>

using namespace std;

class A
{
    int res;
public:
    A(int choice)
    {
        int (*plus)(int, int) = A::add;
        int (*minus)(int, int) = A::subtract;
        if(choice == 1)
            res = operation(7, 5, plus);
        if(choice == 2)
            res = operation(20, 2, minus);
        cout << "result of operation = " << res;
    }
static int add(int first, int second)
{
    return first + second;
}

static int subtract(int first, int second)
{
    return first - second;
}

static int operation(int first, int second, int (*functocall)(int, int))
{
    return (*functocall)(first, second);
}
};
maditya
  • 8,626
  • 2
  • 28
  • 28
2

See the below code. The function calls are working without making them static.

class A
{
  public:
  int add(int first, int second)
  {
      return first + second;
  }

  int subtract(int first, int second)
  {
      return first - second;
  }

  int operation(int first, int second, int(A::*functocall)(int, int))
  {
      return (this->*functocall)(first, second);
  }
};
//typedef int(A::*PFN)(int, int) ;
int main()
{
    int  a, b;
    A a_plus, a_minus;
    a = a_plus.operation(7, 5, &A::add);
    b = a_minus.operation(20, a, &A::subtract);
    cout << "a = " << a << " and b = " << b << endl;
    return 0;
}
Pruthviraj
  • 131
  • 3