40
class Foo {
public:
    Foo() { do_something = &Foo::func_x; }

    int (Foo::*do_something)(int);   // function pointer to class member function

    void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }

private:
    int func_x(int m) { return m *= 5; }
    int func_y(int n) { return n *= 6; }
};

int
main()
{
    Foo f;
    f.setFunc(false);
    return (f.*do_something)(5);  // <- Not ok. Compile error.
}

How can I get this to work?

Girish
  • 925
  • 3
  • 10
  • 20

6 Answers6

36
 class A{
    public:
        typedef int (A::*method)();

        method p;
        A(){
            p = &A::foo;
            (this->*p)(); // <- trick 1, inner call
        }

        int foo(){
            printf("foo\n");
            return 0;
        }
    };

    void main()
    {
        A a;
        (a.*a.p)(); // <- trick 2, outer call
    }
Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
  • Tudok, after going through your post a second time I realized that you have given the right answer too (trick 2). Thanks. – Girish Jun 13 '09 at 18:24
  • Your code does not work. I copy/paste and try compile. test_function_pointer_2.C: In constructor 'A::A()': test_function_pointer_2.C:7: error: argument of type 'int (A::)()' does not match 'int (A::*)()' – user180574 Jan 12 '13 at 02:03
  • 1
    @user180574, I remember that it did work. Anyway, you're right. I tested it with gcc and got the same error. I fixed it. – Nick Dandoulakis Jan 12 '13 at 12:15
33

The line you want is

   return (f.*f.do_something)(5);

(That compiles -- I've tried it)

"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.

James Curran
  • 101,701
  • 37
  • 181
  • 258
3
class A {
    int var;
    int var2;
public:
    void setVar(int v);
    int getVar();
    void setVar2(int v);
    int getVar2();
    typedef int (A::*_fVar)();
    _fVar fvar;
    void setFvar(_fVar afvar) { fvar = afvar; }
    void insideCall() { (this->*fvar)(); }
};

void A::setVar(int v)
{
    var = v;
}

int A::getVar()
{
    std::cout << "A::getVar() is called. var = " << var << std::endl;
    return var;
}

void A::setVar2(int v2)
{
    var2 = v2;
}

int A::getVar2()
{
    std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
    return var2;
}

int main()
{
    A a;
    a.setVar(3);
    a.setVar2(5);

//    a.fvar = &A::getVar;
    a.setFvar(&A::getVar);
    (a.*a.fvar)();

    a.setFvar(&A::getVar2);
    (a.*a.fvar)();

    a.setFvar(&A::getVar);
    a.insideCall();

    a.setFvar(&A::getVar2);
    a.insideCall();

    return 0;
}

I extended Nick Dandoulakis's answer. Thank you.

I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.

Volkan Ozyilmaz
  • 470
  • 4
  • 19
0
#include<iostream>
using namespace std;

class A {

public:
    void hello()
    {
        cout << "hello" << endl;
    };

    int x = 0;

};


void main(void)
{

    //pointer
    A * a = new A;
    void(A::*pfun)() = &A::hello;
    int  A::*v1 = &A::x;

    (a->*pfun)();
    a->*v1 = 100;
    cout << a->*v1 << endl << endl;

    //----------------------------- 
    A  b;
    void(A::*fun)() = &A::hello;
    int  A::*v2 = &A::x;

    (b.*fun)();
    b.*v2 = 200;
    cout << b.*v2 << endl;

}
SaeidMo7
  • 1,214
  • 15
  • 22
0

Try (f.*do_something)(5);

SuPra
  • 8,488
  • 4
  • 37
  • 30
-4

I think calling a non static member of the class could also be done using a static member function.

  • 1
    This is not possible. "When modifying a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. When modifying a member function in a class declaration, **the static keyword specifies that the function accesses only static members**." See [MSDN reference](http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx) – ForceMagic Jul 19 '12 at 01:04
  • well, you could keep a list of all instances trough the constructor and then call it for all instances, but i guess that is somewhat of a whack idea :p – Willem D'Haeseleer Jul 30 '12 at 14:28