views:

118

answers:

7

There is a class

class A {
public:
    A() {};

private:
    void func1( int ) {};
    void func2( int) {};


};

I want to add a function pointer which will be set in constructor and points to func1 or func2.

So I can call this pointer (as class member) from every class procedure and set this pointer in constructor.

How can I do it?

+1  A: 

Add a member variable

void (A::*ptr)();

set it in the constructor

ptr=&A::func1;

(or use the initializer list) and call it in methods of A:

(this->*ptr)();
jpalecek
(this->*ptr)(), not this->*ptr()
Tomek
@Tomek: Thanks, corrected.
jpalecek
A: 

See boost::function (http://www.boost.org/doc/libs/1_43_0/doc/html/function.html) to handle in a c++ way function and class member pointers.

For example (from boost::function documentation) :

struct X {
  int foo(int);
};

boost::function<int (X*, int)> f;

f = &X::foo;

X x;
f(&x, 5);
Scharron
A: 

Some example...

class A; // forward declaration
typedef void (A::*func_type)(int);

class A { 
public:
  A() {
    func_ptr = &A::func1;
  }

  void test_call(int a) {
    (this->*func_ptr)(a);
  }

private:
  func_type func_ptr;

  void func1(int) {}
  void func2(int) {}
};
SirDarius
(this->*ptr)(), not this->*ptr()
Tomek
+4  A: 
class A {
public:
    A(bool b) : func_ptr_(b ? &A::func1 : &A::func2) {};

    void func(int i) {this->*func_ptr(i);}

private:
    typedef void (A::*func_ptr_t_)();
    func_ptr_t_ func_ptr_;

    void func1(int) {};
    void func2(int) {};
};

That said, polymorphism might be a better way to do whatever you want to do with this.

sbi
Definitely. This is tricky and unusual syntax for a reason. This is exactly the problem OO solves easily.
Scott Stafford
A: 

I compiled and ran this code. The various members need to be public so you can pass them into the constructor. Otherwise, here you go.

However, I agree with other posters that this is almost definitely a bad thing to do. ;) Just make invoke pure virtual, and then make two subclasses of A which each override invoke().

#include <iostream>
using namespace std;

class A;
typedef void(A::*MyFunc)(int) ;

class A { 
    public: 

        A() {}
        A(MyFunc fp): fp(fp) {}

        void invoke(int a)
        {
            (this->*fp)(a);
        }

        void func1(int a) { cout << "func1 " << a << endl; }
        void func2(int a) { cout << "func2 " << a << endl; }
    private: 

        MyFunc fp;
};

int main()
{
    A* a = new A( & A::func1 );
    a->invoke(5);
    A* b = new A( & A::func2 );
    b->invoke(6);
}
Scott Stafford
A: 

Why do you think it's a bad thing to do. I just need one function pointer and I don't want to create two subclasses for this. So why is it so bad?

Nikita
You don't have to create two subclasses for it, `A a`; is to define a variable of A, and `a(1, 123)`, it's a function call, and is calling func1 with input param being 123; function pointer can definitely handle your request, but functor is easier to use and the grammar is elegant. When someone needs more complicated features of calling functions, such as saving state or so, they definitely have to use functors. If you think functor can meet all your request, I am totally OK with that. I have no problem if you use C++ as "C with classes" but as a matter of factd, C++ is much more than that.
shader
A: 

I suggest you use functor(or function object), rather than function pointer, because the former is safer, and function pointer can be difficult or awkward to pass a state into or out of the callback function

A functor is basically a re-implementation of operator() of class A, for very detailed description please refer to Wikipedia: http://en.wikipedia.org/wiki/Function_object

The code should be something like this:

class A {
public:
    A() {};
    void operator()(int function_index, int parameter) {
    if(function_index == 1)
        func1(parameter);
    else if(function_index == 2)
        func2(parameter);
    else
        { //do your other handling operation
        }
  }


private:
    void func1( int ) {};
    void func2( int) {};
};

By using that class:

A a;
a(1, 123); //calling func1
a(2, 321); //calling func2
shader