Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ function-pointer and inheritance

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;

like image 473
Andrew Avatar asked Jul 21 '26 18:07

Andrew


2 Answers

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;
    }
};
like image 110
Ben Voigt Avatar answered Jul 23 '26 09:07

Ben Voigt


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
}
like image 25
GManNickG Avatar answered Jul 23 '26 10:07

GManNickG