Passing a member function of a class to a parameter outside the class

1.7k Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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.

  • This adds semicolons after the ends of class definitions
  • This removes the semicolon after method declarations when you are supplying bodies in the class
  • You needed various forward definitions to get it to work as you had it, this doesn't require them
  • When a function takes no parameters, it's customary to define as void foo() not void foo(void). return; as the last line of a function returning no value is kind of superfluous as well.
  • Avoid writing new C++ code using printf, learn iostreams
  • Bias member variables to being private or protected.
  • On StackOverflow code samples try and keep them short and not need scroll bars; it's best to not give opening braces their own line (most of the time)

While naming is subjective, I'd suggest that giving your class names initial caps is a better idea than giving variables initial caps.