Pergunta

I am having difficulty getting my head around how to pass a class member function to a subclass (not derived).

My top level class is like this:

class CTop
{
public:
    CTop();
    int func1(void);

private:
    CFnList* _funcList;
};

CTop::CTop():
    _funcList(0)
{
    _funcList = new CFnList();
    _funcList->addFnPtrToList(0, &CTop::func1);
}

int CTop::func1(void)
{
    // Does some stuff...
}

My function list class is like this:

class CFnList
{
public:
    // Public functions
    CFnList();
    void addFnPtrToList(int index, int (*fn)(void));

private:
    // Fn pointer list
    typedef struct
    {
        int index;
        int (*fn) (void);
    }fn_list_t;

    // function pointer list
    QVector<fn_list_t> _fn_list;
};

So basically here I have an instance of class CTop and one of its members is a pointer to a class CFnList. CFnList pointer is instantiated in the constructor of CTop. Then I want to pass in a pointer to one of CTop's member functions to CFnList by calling the following line: "_funcList->addFnPtrToList(0, &CTop::func1);" I get issue (quite rightly) that addFnPtrToList does not take the parameters (int, (CTop::*)()). So the compiler knows this function is a certain member function and not just a generic (maybe static) function.

Is there a way to pass the a pointer to the member function into the sub-class? In my case I want the sub-class to be able to call this function. I am thinking I probably have to make static member functions or something, but the syntax is eluding me on how to do this.

All help / advise appreciated. Fodder

Foi útil?

Solução 2

A declaration in the form:

int (*fn)(void)

cannot point to a member function. It can only point to a free function. Philispophically, this is because the calling conventions for member functions are different then that for free functions. Consider for example the need for a this pointer in the context of a member function call.

The syntax for declaring a pointer-to-member-function is like this:

int (CTop::*fn)(void)

There is an entire section in the C++ FAQ dedicated to member function pointers. Check it out.

Outras dicas

CTop::func1 is a member function. &CTop::func1 is NOT a function pointer, it is a pointer to member (function). Those can not be mixed either in storing or calling. it is not compatible with int (*fn)(void), as the latter takes no arguments and the former requires an object that is passed as the hidden this.

For these reasons you can't have a simple but uniform facility. You either can go with simple function pointers, or pairs of PTM+object pointer, or use wrappers -- handmade or stock like boost::function fueled by boost::bind. If you have C++11 or TR1 you can use the std:: equivalents of the latter.

You are passing the member function as if it were a regular function. That fails to include the 'this' reference to the class. In order to pass member functions, you have to be able to re-reference it from the original 'this'. Take a look at the following, instead.

typedef void (CTop::*OBJFNC)(args);

_funcList = new CFnList();
_funcList->addFnPtrToList(0, this, &CTop::func1);


void addFnPtrToList(int index, CTop* pobj, OBJFNC pfnc)
{ ... Store both ...
}

Now elsewhere you can execute it with the following.

(pobj->*pfnc)(args);

Here is the final solution, it uses a mixture of passing the instance of the object CTop and usage of template class for CFnList:

My top level class is like this (more or less the same except for the declaration of _funcList to includes the class type and to pass in the "this" to the constructor:

class CTop
{
public:
    CTop();
    int func1(void);

private:
    CFnList<CTop>* _funcList;
};

CTop::CTop():
    _funcList(0)
{
    _funcList = new CFnList(this);
    _funcList->addFnPtrToList(0, &CTop::func1);
}

int CTop::func1(void)
{
    // Does some stuff...
}

My function list class is like this:

template<class T>
class CFnList
{
public:
    // Public functions
    CFnList(T *parent);
    void addFnPtrToList(int index, int (T::*fn)(void));

private:
    // Pointer to the parent (or owner is perhaps more correct)
    T* _parent;

    // Fn pointer list
    typedef struct
    {
        int index;
        int (T::*fn) (void);
    }fn_list_t;

    // function pointer list
    QVector<fn_list_t> _fn_list;
};

// Constructor
template <class T>
CFnList<T>::CFnList(T *parent) :
    _parent(parent),
    _fn_list(0)
{
}

// addFnPtrToList:
template <class T>
void CFnList<T>::addFnPtrToList(int index, int (T::*fn)(void))
{
    _fn_list.append((fn_list_t){index, fn});
}

So the major changes are: 1. Pass the CTop type in by using changing CFnList into a template. 2. Pass in the instance of the object CTop (so that the pointer to the function can be called) by passing "this" into the constructor and then template class stores it as a pointer to the given template type.... vio-la!...easy :o

Thanks to all who contributed :))

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top