views:

44

answers:

3

Ok, it's been a while since I wrote in C++. and I've never done anything quiet this high level.

So basically I need to create a class. The constructor for the class needs to take a reference (or pointer) to a method form another class, or to a function.

Basically I have a class that needs to on occasion read a value from a fltk valuator (version 1.1.x), and then change some stuff about itself. Each object will have it's own valuator associated with it. (they also have a link to another object of the same parent, which after updating them selves from the valuator will tell to update, and so on)

So how do i pass functions around, in constructors?

+3  A: 

Here is an example where a method of Foo is passed to the Bar constructor and later invoked on a given Bar object:

struct Foo
{
    int z;

    int add(int x, int y)
    {
        return x + y + z;
    }

    int mul(int x, int y)
    {
        return x * y * z;
    }
};

typedef int (Foo::*foo_method)(int, int);

struct Bar
{
    foo_method m;

    Bar(foo_method m) : m(m) {}

    int call_on(Foo* foo)
    {
        return (foo->*m)(4, 2);
    }
};

int main()
{
    Bar bar(&Foo::add);

    Foo foo = { 123 };
    bar.call_on(&foo);
}

If, on the other hand, you already know the Foo object at Bar construction time, then Bar does not really care which class the method belongs to. All it needs is a functor to call later, and the Foo object can simply be bound by the client.

#include <functional>

struct Bar
{
    std::function<int (int, int)> f;

    Bar(std::function<int (int, int)> f) : f(f) {}

    int call()
    {
        return f(4, 2);
    }
};

using namespace std::placeholders;

int main()
{
    Foo foo = { 123 };
    Bar bar(std::bind(&Foo::add, &foo, _1, _2));

    bar.call();
}

If you don't have a C++0x compiler, replace std::bind with std::tr1::bind or boost::bind.

FredOverflow
It is the latter case, unfortunatly I am stuck with GCC 3.42.(dev c++), i don't want to update as this is the one my assessor will be using aswell.I think I'll carry the whole object just to access it's methods.
Oxinabox
@Oxi: So does `Bar` know at compile time which `Foo` method to call? In that case, you don't need function pointers at all.
FredOverflow
+1  A: 

Your constructor might look something like this:


// convenient typedef. This is for a pointer to a function in Foo
// The function returns void and takes no parameters.
typedef void (Foo::*FooPtr)();

class Bar {
public:
   Bar (FooPtr foo_ptr);
};

Check out some web references for more details on the syntax for pointer-to-members. It's a lot easier if you get familiar with it first.

As an additional note, check out the functions mem_fun and mem_fun_ref. These may do what you need.

JoshD
Actually It might not be a member of a class.It might be a function, i've created as little more than wrapper (say for converting degrees to radians).
Oxinabox
@Oxi: "it might not" -> it actually is not? Or do you want to allow both?
FredOverflow
+1  A: 

The easiest way to capture this is with boost::function. It can store function pointers, but also the result of binding a member function to an object.

For instance,

class Foo {
  Foo(boost::function<int(void)>);
};

will allow you to accept any source of integers.

MSalters