1

This question is similar to what I'm trying to do Calling C++ member function pointer from a struct . However my structure contains a member function pointer that is defined in a different class then the one the structure is defined and used in. Here is some example code of how my classes, structures and function pointers are laid out.

// Alpha.h:
class Alpha{
public:
    void function1(char name[], int number);
    void function2(char name[], int number);
    void function3(char name[], int number);

    typedef void (Alpha::*My_func_ptr)(char name[], int number);

    static My_func_ptr functionTable[];
};

// Alpha.cpp:
#include "Alpha.h"

Alpha::My_func_ptr Alpha::functionTable[] = {
    &Alpha::function1, 
    &Alpha::function2, 
    &Alpha::function3
};

void Alpha::function1(char name[], int number)
{
    //some stuff
}

void Alpha::function2(char name[], int number)
{
    //some stuff
}

void Alpha::function3(char name[], int number)
{
    //some stuff
}

// Beta.h:
#include "Alpha.h"

typdef struct{
    char bName[10];
    Alpha::My_func_ptr fptr;
}ptr_structure;

class Beta{
public:
      void betafunction();

      Alpha alphaobject;
      ptr_structure str_array[3];
};

// Beta.cpp:
#include "Beta.h"

void betafunction()
{
    str_array[0].fptr = alphaobject.functionTable[0];
    str_array[1].fptr = alphaobject.functionTable[1];
    str_array[2].fptr = alphaobject.functionTable[2];

    (str_array[0].fptr)("name", 1); //gives error expression must have 
                                    //(pointer-to-)  function type

    (this->*str_array[0].fptr)("name", 1);
    //error pointer-to-member selection class types are incompatible "Beta" and "Alpha"

    //sample function pointer call using function table from other class,
    //this syntax compiles and runs without error.
    (alphaobject.*Alpha::functionTable[0]("name", 1); 
}

As you can see I can call the function pointer from an array, but can't seem to figure out how to call a function pointer from inside an array of structures.

Community
  • 1
  • 1
ryan
  • 21
  • 4
  • 6
    Please try to differentiate `function pointer` from `member function pointer`, they are very different. – Jesse Good Mar 12 '12 at 21:33
  • Also, your code doesn't compile (for one, a typo `typdef`). Always copy the code as it actually is. – Ed S. Mar 12 '12 at 21:37
  • Thanks Jesse, should I edit the title or just add that to the question text? – ryan Mar 12 '12 at 21:38
  • Ed S, thanks for the suggestion, however that would involve several large files and lots of extraneous information that would detract from the important parts of the code relevant to my question. – ryan Mar 12 '12 at 21:42
  • No, I just mean to copy and paste instead of typing stuff in. I assume that your code actually compiles, but it would not with that typo. – Ed S. Mar 12 '12 at 21:43
  • -1, the code still won't compile. Trying the code you're posting in a compiler is the least you can do. – avakar Mar 12 '12 at 21:46
  • This is actually a question about member function pointers. There are tons of duplicates, [here's one of them](http://stackoverflow.com/q/5499155/500104). – Xeo Mar 12 '12 at 21:50
  • Xeo, I'm not trying to pass a member function pointer, I'm trying to call one from inside an array of structures. Thanks for your help though and I'd appreciate any other links you think may answer this question. – ryan Mar 12 '12 at 21:56
  • That's still just "calling a member function pointer", nothing more, nothing less. – Xeo Mar 12 '12 at 22:02
  • @Xeo: The syntax of it is a bit more complicated due to the member pointers being in an array, and in a static member of a class. For an experienced C++ user well-versed in operator precedence, it's simple. For someone who isn't, it's a valid question. – Nicol Bolas Mar 12 '12 at 22:08

3 Answers3

3

When calling a through member function pointer, you need to have an instance of the object associated with that pointer:

 (alphaobject.*(str_array[0].fptr))("name", 1)
  ^^^^^^^^^^^
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Thank you very much Michael, this was the answer. I'm guessing because I was calling the function pointer, which was declared inside Alpha, I need an object of that class to access that pointer. Do you have any suggested reading to help me understand your answer better? – ryan Mar 12 '12 at 22:09
0

I would think:

(object.*functionTable[0])(args, ...);
(objptr->*functionTable[0])(args, ....);

IIRC, the combination of object and the .* operator is like a big unary operator. So that has lower precedence to the [0] postfix. However, it also has lower prededence than the function call postfix operator (args, ...)

Analogy:

(*foo)();  /* classic C */

Of course the * operator is not required when calling a regular function. But if you do write it, you need the parens, because *foo() means something else.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • Thanks for your input, but the object.*Alpha::functionTable[0] call was an example of working syntax, I thought that might help people. I'm trying to get the function pointer call (str_array[0].fptr)(args) to work. – ryan Mar 12 '12 at 22:04
  • The answer follows from this one. You just took `functionTable[0]` and stored it somewhere else. So replace the expression `functionTable[0]` with one which accesses that "somewhere else". You still need the object; you cannot call a pointer-to-member without an object whose class it is a member of. I.e. (object.*(EXPR))(args, ...); where EXPR references the pointer-to-member, wherever it is. And the class of the pointer-to-member has to match the class of object, of course! – Kaz Mar 12 '12 at 22:08
  • Also, why are you using `this` in a non-member function? What do you expect that to evaluate to and what is the type of that thing? – Kaz Mar 12 '12 at 22:09
  • You're right, when you said to replace the functionTable[0] with something that accesses that same memory it clicked for me. The "this" part was from an answer to a similar question, I wanted to show that that answer did not work. Thanks again for your help. – ryan Mar 12 '12 at 22:19
  • Sometimes doing algebraic manipulation on code helps. This expression works, okay, so what if we substitute this subexpression with another one that means the same thing; it should all be the same. – Kaz Mar 12 '12 at 22:58
0

You can go to one of two solutions, depending on how readable you want the code. The unreadable version (which might even be wrong, and I won't even try to compile):

void Beta::betafunction() {
   Alpha a;
   (a.*(strArray[0].fptr))("name",1);
}

But I would actually try to make things a bit simpler:

void Beta::betafunction() {
   Alpha a;
   Alpha::My_func_ptr mptr = strArray[0].fptr;
   (a.*mptr)("name",1);
}

I believe the second to be much more readable, and the compiler can optimize away mptr pretty easily, so there is no point in trying to play guru with the syntax.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489