0

I'm trying to send a pointer to a class function as a variable to another class. I'm trying to keep both classes separate so I can reuse the code without having to edit it in the future.

I'm compiling on Windows 7, using Visual Studio 2015.

DATASTRUCT dataItem = {0, 1, 0, 1, dataText, parentClass::doSomething};

childClass.addItem(dataItem); //childClass is initiated as a member of parentClass

Elsewhere:

typedef struct dataStruct{
    double min_x;
    double max_x;
    double min_y;
    double max_y;
    GLTEXT label; //custom struct for text information
    void(*function)(void);
}DATASTRUCT;

I want childClass to be able to go about its business and check for certain parameters, and when childClass is done I want it to call doSomething from parentClass, without actually knowing it's a nested class.

The error I get during compile is:

void(parentClass::)() cannot be used to initialise an entity of void()().

I am able to define a standard function and call that, but that's not unique to each parentClass, and I then have to specify which parentClass::doSomething to which I am referring.

The simplest solution I have found is to redefine the pointer to function in childClass to void(parentClass::*)(), which is exactly what I want, but not how I want it.

With that said, I don't know where to take this, is there another way? Something similar?

Edit:

If possible, how would I explicitly send the information required for my childClass to properly interpret the function pointer dynamically.

So...

childClass.addItem(classInformation, dataItem, &parentClass::doSomething);

Or does the receiving end always have to know "parentClass::" in advance? Would this then be a good time to use void pointers?

Am I chasing after my own tail or is this going somewhere?

Edit:

Something like this seems dangerous, but, here it is.

childClass.addItem(classInformation, dataItem, static_cast<void*>(&parentClass::doSomething));

childClass::callParent(classInformation, void*function){
    static_cast<classInformation.something*>(function)();
}

What would "classInformation.something" be in this case?

Jarred
  • 67
  • 6
  • Member funcctions require an object they would operate on. How would you specify which one you want to access in your case? – Revolver_Ocelot Jan 22 '16 at 14:34
  • BTW, you really should use `&parentClass::doSomething`. Only MSVC will forgive you that missed `&`, and that's only because they try to be bug-compatible with VC++6. – MSalters Jan 22 '16 at 15:34
  • @MSalters I'll keep that in mind, I used to add & before my function pointers in c, but I started getting weird errors in c++ for similar pointers. So far I've noticed Visual Studio seems to prefer without. – Jarred Jan 23 '16 at 02:50

2 Answers2

0

The problem is that the class member function needs to know where class variables are, which it can't know if all it has to go on is a function pointer to the class function without a reference to the object that it is a member of. So a parentClass::* implicitly has a pointer to the object, whereas a function pointer does not.

Fundamentally, you need to keep track of the object in order to call one of its member functions. You can use a pointer to the object and call the member function from it, or you can use a parentClass::* which does almost the same thing behind the scenes.

Perhaps there is a more basic underlying question that will let you get around this limitation. For example, rather than asking if you can do this, maybe there's a different way you can accomplish whatever you are trying to do with it.

Tom
  • 939
  • 5
  • 9
  • If you're pointing to a function using the classes pointer to function, why would the parentClass need to know where the variables are? Isn't that something the function itself is aware of being in a set memory location to begin with? – Jarred Jan 23 '16 at 02:47
  • The member function itself is in a memory location, but it doesn't know which instance of the class it is a part of without being passed a pointer by the compiler. The member function is compiled and linked and then just one copy of it is sitting somewhere in memory. The program doesn't make a new copy of that code each time a new object is created--which means the same code gets called for ALL instances of that class, so the code doesn't know which instance is calling it unless it gets passed a pointer. The compiler passes it the pointer implicitly. But a simple function pointer won't. – Tom Jan 23 '16 at 04:02
  • Okay, that makes a lot more sense to me when explained that way. I guess the question should have been how to pass a pointer to a class function explicitly specifying which class instance without specifying the class type specifically..? I'm just confusing myself now. – Jarred Jan 23 '16 at 05:09
0

Function pointers are really limiting. I would suggest to use std::function<void()> instead. Note that you will still have to tell which object member function would operate upon. You can use std::bind or lambda to do that:

DATASTRUCT dataItem = 
    {0, 1, 0, 1, dataText, std::bind(&parentClass::doSomething, std::ref(someParentClassObject))};
//or
DATASTRUCT dataItem = 
    {0, 1, 0, 1, dataText, [&someParentClassObject](){ someParentClassObject.doSomething(); }};
Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48
  • Never heard of it before, looked confusing, but I finally had time in front of the computer to try it and it worked no problems using std::function/bind. Not to mention this makes no difference to the function call in line, preserving my desired format. You're a beast. Go have a fantastic day. – Jarred Jan 23 '16 at 08:30