Reputation: 105
How do you pass a member function of a class as a parameter to another member function of another class?
class theSecondClass
{
public:
void theFunctionReceiver(void (theFirstClass::*Function)(void));
{
// This part is wrong. "Operand of * must be a pointer"
(*Function)();
}
}
class theFirstClass
{
public:
theSecondClass * SecondClassInstance;
void theFunctiontoPass(void)
{
printf("It worked \n");
return;
}
void theFunctiontoCall(void)
{
SecondClassInstance->theFunctionReceiver(theFunctiontoPass);
}
};
Take the assumption that theSecondClass
and theFirstClass
are both made already. I'm calling theFirstClass->theFunctiontoCall()
from somewhere.
I don't get it. When I pass it in, isn't it pass in as a pointer?
I've taken a look at several similar threads around, but I don't understand them fully. I'm using VS 2013, basic compiler.
Upvotes: 0
Views: 1893
Reputation: 33607
When you write this statement:
SecondClassInstance->theFunctionReceiver(theFunctiontoPass);
What you presumably meant was:
SecondClassInstance->theFunctionReceiver(&theFunctiontoPass);
Which should give you a compiler warning that it's an unqualified member reference, which would point out to you that what you are actually writing is:
SecondClassInstance->theFunctionReceiver(&theFirstClass::theFunctiontoPass);
You are getting a pointer to a member function on the class definition. The "this" is not implicit or included in the package. The only way you're going to be able to call it without a class instance is if it is static. (In which case it won't type-check as a member function...it will just be an ordinary function pointer.)
If I'm going to pass in a reference to my class, why would I even need to pass it the function? Couldn't I just call it with, in the case of the link, ButtonObj->Buttonfunc();
The only reason you would use pointers to member functions is to get some kind of abstraction, where one piece of code can call a member function it doesn't need to explicitly name. If you're okay with theSecondClass::theFunctionReceiver
knowing the name of theFirstClass::theFunctionToPass
and the identity of theFirstClass
...then sure, just pass a reference to an instance of theFirstClass and call the method explicitly.
You might want a situation where theSecondClass
is going to call any one of a number of member functions on theFirstClass
with matching signatures...it just doesn't want to hard-code which one. In that case, then passing a pair of a class reference and a member function can be done. You seem to suspect this doesn't come up too often as useful, and you would be right. Every year I have to go back and look up the syntax for how to call pointers-to-members on a class, because it almost never comes up except in StackOverflow questions:
How to call through a member function pointer?
More likely what you want (and what people asking those SO questions actually want) is to separate concerns so that theSecondClass
has a hook to execute something, but doesn't need to know about theFirstClass
at all. Look into lambdas, std::function, and std::bind for generalized solutions which you may be able to experiment with to your satisfaction.
Here is an example to show you what that would look like to conveniently wrap up the call abstractly into a std::function. It makes a function object on the spot, that captures the enclosing this
pointer so that when it is invoked it calls the method on the object:
#include <iostream>
#include <functional>
class theSecondClass {
public:
void theFunctionReceiver(std::function<void()> const & Function) {
Function();
}
};
class theFirstClass {
private:
theSecondClass * SecondClassInstance;
public:
void theFunctiontoPass() {
std::cout << "It worked\n";
}
void theFirstClass::theFunctiontoCall() {
SecondClassInstance->theFunctionReceiver(
[this]() {theFunctiontoPass();}
);
}
};
int main() {
theFirstClass tfc;
tfc.theFunctiontoCall();
}
Note this is C++11, which I suggest using if you're not already. Less convenient notations and mechanisms exist in C++98, though.
This corrects problems with your code that go beyond the issue you mention. Please review writing a Minimal, Complete, Verifiable Example. It should be possible to paste your provided code into a compiler and see only the error you wish to discuss.
void foo()
not void foo(void)
. return;
as the last line of a function returning no value is kind of superfluous as well.While naming is subjective, I'd suggest that giving your class names initial caps is a better idea than giving variables initial caps.
Upvotes: 1