0

I try to implement an array of function pointers in an singleton owning a thread. In the thread function I get an error, telling me that a member has to be relative to an object. More in the commentline...

Header:

typedef struct{
  int action;
  HWND handle;
}JOB;

class Class{
public:
  enum Action { 1,2 };

private:
  JOB    m_currentJob;
  queue<JOB> Jobs;

  static DWORD WINAPI ThreadFunction(LPVOID lpParam);

  void (Class::*ftnptr[2])(JOB Job);
  void Class::ftn1(JOB Job);
  void Class::ftn2(JOB Job);

// Singleton pattern
public:
  static Class*  getInstance(){
    if(sInstance == NULL)
      sInstance = new Class();
    return sInstance;
  }
private:
  Class(void);
  ~Class(void);
  static Class*  sInstance;
};

Body:

#include "Class.h"

Class* Class::sInstance = NULL;

Class::Class(){
  this->ftnptr[0] = &Class::ftn1;
  this->ftnptr[1] = &Class::ftn2;
}

DWORD WINAPI Class::AutoplayerThreadFunction(LPVOID lpParam)
{  
  Class *pParent = static_cast<Class*>(lpParam);

  while(true){
   (pParent->*ftnptr[pParent->m_currentJob.action])(pParent->m_currentJob);
   /* The line above causes the compiler error. Curious to me is that 
    * neither "pParent->m_currentJob" nor "pParent->m_currentJob" cause 
    * any problems, although they are members too like the ftnptr array.
    */
  }
}

void Class::ftn1(JOB Job){}
void Class::ftn2(JOB Job){}

A call via getInstance from the SingletonPattern doesnt make it any better. Any suggestions?

ManuelSchneid3r
  • 15,850
  • 12
  • 65
  • 103
  • Is it a grouping issue? Try `(pParent->*(ftnptr[...]))`. – Kerrek SB Oct 13 '12 at 15:26
  • Nope. The cause seems to hide somewhere else. I have this: "(this->*internalUpdate)(hWnd);" somwhere else in the code. Its working fine. – ManuelSchneid3r Oct 13 '12 at 15:33
  • I was specifically referring to the grouping of the square brackets. Your counterexample isn't pertinent, since it doesn't have those. – Kerrek SB Oct 13 '12 at 15:35
  • Okay first of all I missunderstood you. And sencondly I made a copy-paste mistake :D. Well I thought you are just referring to the round brackets. But should that not be irrelevant? I thought the array brackets are one of the most binding operators. Btw I meant "(this->*ftnptr[gs])(JOB Job);" in the example before. But its working fine too. :D – ManuelSchneid3r Oct 13 '12 at 15:59

2 Answers2

1

ftnptr is a member of Class. However, you access it directly. That is, pParent->*ftnptr[...] means "access the member of pParent designated by the pointer ftnptr[...]", but it doesn't imply that ftnptr too is a member of pParent.

The correct code is (pParent->*(pParent->ftnptr[...]))(...). But I would recommend extracting the array index expression from that:

auto fnptr = pParent->ftnptr[...];
(pParent->*fnptr)(...);
Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
0

I think it might be how you declare your array of pointer-to-member-functions. (Edit: This wasn't what was wrong. I'm keeping this answer up anyway, because typedefs for function pointers can really make code cleaner, so I think this is good advice.)

Try using a typedef:

typedef void (Class::*ftnptr)(JOB Job);
ftnptr[2] fn_ptrs;

Then use it like so:

Class::Class(){
  this->fn_ptrs[0] = &Class::ftn1;
  this->fn_ptrs[1] = &Class::ftn2;
}

DWORD WINAPI Class::AutoplayerThreadFunction(LPVOID lpParam)
{  
  Class *pParent = static_cast<Class*>(lpParam);

  while(true){
   (pParent->*(pParent->fn_ptrs[pParent->m_currentJob.action]))(pParent->m_currentJob);
   /* The line above causes the compiler error. Curious to me is that 
    * neither "pParent->m_currentJob" nor "pParent->m_currentJob" cause 
    * any problems, although they are members too like the ftnptr array.
    */
  }
}
Geoff Montee
  • 2,587
  • 13
  • 14
  • Sorry, Stackoverflow was down for maintainence. I did not test it. But after reading the anwser above I think it wont work. Anyway thanks for your efforts. – ManuelSchneid3r Oct 13 '12 at 17:28
  • I'm pretty sure the `typedef` would work. However, it wouldn't solve the problem that the other answer pointed out: trying to dereference a member of the object through the function pointer. To make my answer work, you would have to make the same change. – Geoff Montee Oct 13 '12 at 17:49
  • I added the code to make the above code correct. Using `typedef` for function pointers can really make code cleaner, so I would highly recommend it. – Geoff Montee Oct 13 '12 at 17:52