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?

1
  • 1
    Aren't func_x and func_y static functions even though they're not marked as such? Commented Oct 10, 2012 at 14:05

6 Answers 6

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
    }
Sign up to request clarification or add additional context in comments.

3 Comments

Tudok, after going through your post a second time I realized that you have given the right answer too (trick 2). Thanks.
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, I remember that it did work. Anyway, you're right. I tested it with gcc and got the same error. I fixed it.
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.

6 Comments

Technically, "f.do_something" returns the pointer, and the ".*" operator calls the pointer-to-member function on a class.
So I assume return (f.*Foo::do_something)(5) should also work.
@ThomasMcLeod It does not.
Ah, but this means that if you have Foo g, then this would also compile and run: return (g.*f.do_something)(5); Right? (even if there's no good reason to do that)
@ThomasMcLeod no, because Foo::do_something names the data member of the class. You need an instance to access a non-static data member.
|
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.

3 Comments

Rather than only post a block of code, please explain why this code solves the problem posed. Without an explanation, this is not an answer.
@MartijnPieters I wrote that it is extended from Nick Dandoulakis answer. It was explained in there. I am new in stackoverflow maybe I need to do in a different way.
Well, you could explain what you changed, for example, and why.
0

Try (f.*do_something)(5);

Comments

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;

}

Comments

-4

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

2 Comments

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
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.