How can I pass a member function where a free function is expected?
There isn't anything wrong with using function pointers. However, pointers to non-static member functions are not like normal function pointers: member functions need to be called on an object which is passed as an implicit argument to the function. The signature of your member function above is, thus
void (aClass::*)(int, int)
rather than the type you try to use
void (*)(int, int)
One approach could consist in making the member function static
in which case it doesn't require any object to be called on and you can use it with the type void (*)(int, int)
.
If you need to access any non-static member of your class and you need to stick with function pointers, e.g., because the function is part of a C interface, your best option is to always pass a void*
to your function taking function pointers and call your member through a forwarding function which obtains an object from the void*
and then calls the member function.
In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types. If using a templated interface is undesirable you should use something like std::function<void(int, int)>
: you can create a suitably callable function object for these, e.g., using std::bind()
.
The type-safe approaches using a template argument for the class type or a suitable std::function<...>
are preferable than using a void*
interface as they remove the potential for errors due to a cast to the wrong type.
To clarify how to use a function pointer to call a member function, here is an example:
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, nullptr);
foo object;
somefunction(&forwarder, &object);
}
Passing a pointer to a member function as argument for a void* function
I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.
Is this possible in C++?
Yes, it is possible, but you need to use a more flexible type. The way to achieve this is to specify the PerformAction
function with a different type. You want to use a type that is callable with zero arguments and returns void
, std::function<void ()>
. For example change the PerformAction
function to be: void PerformAction(std::function<void ()> fn);
. This version will allow you to accept anything that's callable with zero arguments and returns void
, see the following code for an example.
Example Code
#include <functional>
#include <iostream>
class Foo
{
public:
void bar() { std::cout << "Member function: Foo::bar()\n"; }
};
void bar()
{
std::cout << "Free function: bar()\n";
}
class Functor
{
public:
void operator()() { std::cout << "Functor object\n"; }
};
auto lambda = []() { std::cout << "Lambda expression\n"; };
void doSomething(std::function<void ()> fn)
{
fn();
}
int main()
{
doSomething(bar);
doSomething(Functor());
doSomething(lambda);
Foo foo;
doSomething(std::bind(&Foo::bar, &foo));
return 0;
}
Live Example
Example Output
Free function: bar()
Functor object
Lambda expression
Member function: Foo::bar()
How do I pass a member function to a function that expects a function pointer?
The problem here is that a member function expects a "hidden" first argument that is a this
pointer. Loosely speaking, a member function
void Func(int a, double b);
is equivalent to a free function
void Func(MyClass* this, int a, double b);
There is no way to pass a this
pointer via ClassicFuncPtr
, and std::function
tricks won't help you here. target()
doesn't do any magic, it just returns a pointer to the stored function if types match, and in your code they don't, that's why you get a null pointer. std::bind
returns a functional object (that stores this
inside), but a functional object is quite distinct from a function pointer and can't be converted into one.
Given that you can't change the callback type, there is a pretty ugly and fragile work-around that uses a static
variable to store the value of this
pointer. It should give you the idea of how to make it work, at least in principle.
class MyClass {
public:
void Test() {
thisPtr = this;
CallMyFunc(MemberFuncInvoker);
}
private:
inline static MyClass* thisPtr;
static void MemberFuncInvoker(int a, double b) {
thisPtr->MemberFunc(a, b);
}
void MemberFunc(int a, double b) {
std::cout << "a = " << a << ", b = " << b << '\n';
}
};
Note that static
member functions don't expect a hidden this
argument and behave like free functions in this respect (due to the absence of this
argument, you can't access non-static
data members inside a static
member function).
Demo
Typically, callbacks are accompanied with a void*
-like parameter that can be used to pass a this
pointer. For example, theEnumWindows
function from WinAPI has the signature
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);
That lParam
is passed to a callback
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
Then, inside a free (or static
) callback function you could do:
reinterpret_cast<MyClass*>(lParam)->MyMemberFunction(hwnd);
Passing a function pointer to a member function in C++.Getting error
Let's deal with the two issues in the post.
You are calling
fun1
andfun2
. Since their return type isvoid
, you can't pass their result as something's value. In particular as the value of a function pointer. You also can't obtain their address by using the dot member access operator. Which brings us to the following.Member functions are not like regular functions. You cannot just take their address. Their treatment is special, because member functions can only be called on an object. So there's a special syntax for them, which involves the class they belong to.
Here's how you would do something like what you are after:
class student
{
public:
void fun1() { printf("Fun1\n"); }
void fun2() { printf("Fun2\n"); }
// A function that receives a member function
// as parameter and calls the function
void wrapper(void (student::*fun)())
{
(this->*fun)();
}
};
int main()
{ student s;
s.wrapper(&student::fun1);
s.wrapper(&student::fun2);
return 0;
}
Pass member function pointer to parent class yields compiler error
If I understand the goal (and believe me, that's a sketchy 'if'), you want to specify some member of some A
derivation to invoke from some A
member as a dispatched 'callback' mechanic. If that is the case, then to answer your question in comment, yes, a function and bind can do this. It can even be semi-protected with a little help from sfinae:
Example
#include <iostream>
#include <type_traits>
#include <functional>
#include <memory>
struct A
{
virtual ~A() = default;
std::function<void(int)> callback = [](int){};
template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
callback = std::bind(pfn, dynamic_cast<Derived*>(this), _1);
}
void fire(int arg)
{
callback(arg);
}
};
struct B : public A
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};
struct Foo
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};
int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}
Output
void B::memberfn(int):42
The Parts
The first part is straight forward. We declare a member variable callback
to be a std::function<void(int)>
instance. This is where we'll eventually bind our callable object point. The default value is a lambda that does nothing.
The second part is... a little more complicated:
template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))
This declares registerCallback
as an available member function that accepts a non-static member function pointer taking one int
as an argument, but only if the class hosting that member function, or a derivative therein, is a derivation of A
(or A
itself). Some non-A
derivative Foo
with a member void foo(int)
will not compile.
Next, the setup to the callback itself.
using namespace std::placeholders;
callback = std::bind(pfn, dymamic_cast<Derived*>(this), _1);
This just binds the pointer-to-member to this
dynamic-cast to the derivation type (which had better work or we're in trouble, see final warning at the end of this diatribe), and sets the call-time placeholder. The _1
you see comes from the std::placeholders
namespace, and is used to delay providing an argument to the callback until such time as we actually invoke it (where it will be required,and you'll see that later). See std::placehholders
for more information.
Finally, the fire
member, which does this:
void fire(int arg)
{
callback(arg);
}
This invokes the registered function object with the provided argument. Both the member function and this
are already wired into the object. The argument arg
is used to fill in the placeholder we mentioned earlier.
The test driver for this is straightforward:
int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}
This creates a new B
, hosting it in a dynamic A
pointer (so you know there is no funny business going on). Even with that, because B
derived from A
the registerCallback
sfinae filtering passes inspection and the callback is registered successfully. We then invoke the fire
method, passing our int
argument 42
, which will be sent to the callback, etc.
Warning: With great power comes great responsibility
Even those there is protection from passing non-A
derived member functions, there is absolutely none from the casting itself. It would be trivial to craft a basic A
, pass a B
member (which will work since A
is its base), but there is no B
actually present.
You can catch this at runtime via that dynamic_cast
, which we're currently not error checking. For example:
registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
Derived *p = dynamic_cast<Derived*>(this);
if (p)
callback = std::bind(pfn, p, _1);
}
You can choose the road more risky. Personally, i'd detect the null case and throw an exception just to be safe(er)
Pass Member Function as Parameter to other Member Function (C++ 11 <function>)
ClassName::add
is a non-static member function, an instance of ClassName
is needed for it to be called on; it can't be used as the argument for std::function<double (double,double)>
directly.
You can use lambda and capture this
(as @Igor Tandetnik commented):
return intermediate(a, b, [this](double x, double y) { return add(x, y); } );
or use std::bind and bind this
pointer:
return intermediate(a, b, std::bind(&ClassName::add, this, _1, _2));
or make ClassName::add
a static member function or a non-member function (it could be because it doesn't use any members of ClassName
). e.g.
class ClassName
{
public:
static double add(double a, double b);
...
};
Related Topics
Why Does C++11 Not Support Designated Initializer Lists as C99
Benefits of Initialization Lists
Why Do Constant Expressions Have an Exclusion For Undefined Behavior
Is Ncurses Available For Windows
Why Aren't Pointers Initialized With Null by Default
How to Construct a Std::String With Embedded Values, I.E. "String Interpolation"
Have You Used Any of the C++ Interpreters (Not Compilers)
How to Sort Two Vectors in the Same Way, With Criteria That Uses Only One of the Vectors
How Is "=Default" Different from "{}" for Default Constructor and Destructor
Selectively Disable Gcc Warnings For Only Part of a Translation Unit
Boolean Expression (Grammar) Parser in C++