views:

118

answers:

2

I have an generic math-method, that operates under a set of functions (with a lot of variables and states, so it can't be static). I've implemented method in parent class and I want to declare a different set of functions in every child-class.
I've try to do something like this:

class A {
public:
    typedef int (A::*func)();
    func * fs;
    void f() { /*call functions from this->fs*/ }
};

class B : public A {
public:
    int smth;

    B(int smth) {
         this->smth = smth; //user-provided variables

        //there may be a lot of functions with same interface
        this->fs = new func[1];
        fs[0] = &B::f;
    }

    int f() {
        return smth + 1;
    }
};

It fails with this error: error C2440: '=' : cannot convert from 'int (__thiscall B::* )(void)' to 'A::func'

Or "IntelliSense: a pointer to a bound function may only be used to call the function" if I try to use &this->f;

+1  A: 

Maybe an array of boost::function would work:

#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <vector>

struct A
{
    virtual ~A(void) {}; // base classes should always have virtual destructors

    typedef std::vector<boost::function<int(void)> > function_array;
    function_array mFunctions;
};

struct B : A
{
    B(int pX) : mX(pX) // use initializer lists
    {
        mFunctions.push_back(boost::lambda::bind(&B::foo, this));
    }

    int foo(void)
    {
        return mX + 1;
    }

    int mX;
};

int main(void)
{
    B b(5);
    A& a(b);

    int x = a.mFunctions[0]();
    // x is 6
}

Your goals are still unclear. (In the above, it doesn't really make sense for A to be a base class. Why not have a function like get_functions that just returns an array of functions all setup and ready to use, for example?)


What's your bigger picture here? Sounds like you're looking for virtual functions:

struct A
{
    virtual ~A(void) {} // base classes should always have virtual destructors

    virtual int foo(void) const = 0;
};

struct B : A
{
    B(int pX) : mX(pX) {}

    int foo(void) const
    {
        return mX + 1;
    }

    int mX;
};

int main(void)
{
    B b(5);
    A* a = &b;

    int x = a->f(); // calls B::foo(), polymorphic behavior thanks to virtual
    // x is 6
}
GMan
I can't use virtual functions, because number of them may vary in every child-class.
Andrew
@pingvinus: Then you'll have to enlighten us on what the bigger picture is. Show us your goals, not the method you think you need to get there. (That's what we're for.)
GMan
+2  A: 

Curiously recurring template pattern would help.

template<typename Derived>
class A {
public:
    typedef int (Derived::*func)();
    func * fs;
    void f()
    {
        Derived* const This = static_cast<Derived*>(this);
        /* call functions like (This->*(fs[0]))() */
    }
};

class B : public A<B> {
public:
    int smth;

    B(int smth) {
         this->smth = smth; //user-provided variables

        //there may be a lot of functions with same interface
        this->fs = new func[1];
        fs[0] = &B::f;
    }

    int f() {
        return smth + 1;
    }
};
Ben Voigt
Thanks, that work exactly how I want and can be implemented with minor changes in code :)
Andrew
How is this different than not just using `B` and putting it's functions in an array? (i.e., what purpose does A serve?)
GMan
I can have a lot of math-models (B's) and only one method to solve them (A).
Andrew
@pingvinus: But there is no single A.
GMan
@GMan: presumably what is missing is the count of `fs`. It would probably be better to use a `std::vector<func>` instead. Consider for example, that `A` might implement performance comparison between a number of different algorithms defined in `B`. `A` needs to be able to access and time each algorithm independently, but it also needs to have access to the whole set so it can compare the results and make sure they agree within acceptable precision. Also the inputs are stored in member variables of `B` so that all the algorithms have access to them. Just one example of a good use for this.
Ben Voigt