function pointer to a class member - c++

I am trying to do some like this:
class A {
void *(*func)(void *);
A(void *(*function)(void *)){
func = function;
}
}
class B {
void *real_func(void *);
A ptr;
B()
:ptr(&real_func)
{
...
}
}
But I get this error:
error: ISO C++ forbids taking the address of an unqualified or
parenthesized non-static member function to form a pointer to member
function.
Someone knows how to initialize the function pointer to a function member in the same class???
Thanks!
Carlos

Since real_func is not a static member function, its type cannot be void *(*)(). Instead, it is void *(B::*)() so you need to declare func accordingly:
void *(B::*func)();
// call it like this
pointer_to_b->*func();
If you are careful, you can also use pointer to A as the base class, but you must make sure that the pointer to A points to an instance of B:
void *(A::*func)();
At this point, however, you are mostly just replicating the functionality of virtual member functions. So I would recommend you use that instead:
class A {
virtual void *func() = 0;
};
class B {
void *func() {
// ...
}
};

You could create B like this:
struct B {
static void *real_func(void *);
A ptr;
B()
:ptr(&real_func)
{
...
}
};
A static member function acts like a regular function, so you can create a function pointer for it.
If you don't need a regular function pointer, then you can use std::function:
#include <functional>
struct A {
std::function<void *(void*)> func;
A(std::function<void *(void*)> function)
: func(function)
{
}
};
struct B {
void *real_func(void *);
A ptr;
B()
: ptr(std::bind(&B::real_func,this,std::placeholders::_1))
{
}
};

Related

How to pass function pointer (callback) and call it without knowing it's type?

I have a function pointer as a member to a pure virtual base class. I'd like to pass this pointer to a library which does not know about either of these classes, MyBase or MyClass, and then call the function pointer as a callback into MyClass. I'm writing the lib as well. I want the shared library to call a callback in MyClass.
My question is, how does one pass a function pointer as an argument to a function and have it called without knowing anything about the class itself.
I was considering a pointer to a function pointer, but wasn't sure how to cast properly.
class MyBase {
public:
virtual void callback() = 0;
void (MyBase::*callback_ptr)();
};
class MyClass : public MyBase {
public:
MyClass();
void callback() { cout << "callback called" << endl; };
};
main.cpp
{
MyClass my_class;
my_class->callback_ptr = &MyBase::callback;
lib->set_callback(my_class->callback_ptr);
}
lib.cpp
class MyLib {
public:
// how to declare the member function pointer here?
void** callback_ptr;
// how to write sig here?
set_callback(ptr) { callback_ptr = ptr }
running() {
// how to call the callback here w/o knowing it's type?
}
}
#include <iostream>
#include <functional>
using namespace std;
class Foo {
public:
void myFunction() {
cout << "Foo::myFunction()\n";
}
};
void myAPICall(std::function<void()> arg) {
arg();
}
int main(int, char**) {
Foo foo;
// Using a lambda
myAPICall( [&]() { foo.myFunction(); } );
// Using bind
myAPICall( std::bind(&Foo::myFunction, foo) );
return 0;
}
Yields:
$ g++ -std=c++11 f.cpp -o f && f
Foo::myFunction()
Foo::myFunction()
This assumes that you control the API you're calling, and it uses std::function like my code does. If it accepts a C-style function pointer rather than std::function, then you're going to have to play much different games.
To get a function pointer when you don't know the exact type of function that will be called, use std::function from the <functional> header.
class MyLib {
public:
// how to declare the member function pointer here?
std::function<void()> callback_ptr;
// how to write sig here?
void set_callback(std::function<void()> ptr) { callback_ptr = ptr; }
void running() {
callback_ptr();
}
};
To use a member function as a std::function, use std::bind:
int main()
{
MyClass my_class;
MyLib my_lib;
my_lib.set_callback(std::bind(&MyClass::callback, &my_class));
my_lib.running(); // calls my_class.callback()
}

Passing a method pointer for a new method to base class

I'd like to be able to call any arbitary method (which are generic methods) defined in a derived class from the base class. The base class doesn't know about them. I'd somehow like to get this pointer and the virtual table offset and be able to call it. Class A doesn't actually need to be the base class, it could be a separete class which doesn't know anything about B but needs to call the methods. Is it possible?
class A
{
public:
typedef void (A::*Method)();
void call(Method p)
{
//...
}
};
class B : public A
{
public:
virtual void meth1()
{
}
virtual void meth2()
{
}
virtual void test()
{
call(&TestTask::meth1);
call(&TestTask::meth2);
}
};
Errors:
test.cpp:420:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
call(&TestTask::meth1);
^
test.cpp:420:30: note: candidate is:
test.cpp:402:10: note: void A::call(A::Method)
void call(Method p)
^
test.cpp:402:10: note: no known conversion for argument 1 from ‘void (TestTask::*)()’ to ‘A::Method {aka void (A::*)()}’
test.cpp:421:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
call(&TestTask::meth2);
Non-static member functions need an object to act on, so you can't simply call the member-function pointer by itself. You could define a template to call a member of any class, given an object of that class:
template <class Class>
void call(Class & c, void (C::*method)()) {
(c.*method)();
}
If that's not what you want, then you'll need to clarify what you do want.
You can use the CRTP pattern to accomplish what you are trying.
template <typename T> struct A
{
typedef void (T::*Method)();
void call(Method m)
{
(static_cast<T*>(this)->*m)();
}
};
struct B : A<B>
{
void meth1(){}
void meth2(){}
void test()
{
call(&B::meth1);
call(&B::meth2);
}
};

Passing a function pointer to a function

What should I do if I want to pass a non-static member function of any class as a click function of the button ? Is it possible ? If so what do I need to do ? For example in which ever class (EntityToolGUI over here) the button is initiatlized, I want to set its click action to a non-static member function (a non-static member function of class EntityToolGUI ) of that class.
GUIButton.h
typedef void (*ptr2clickFunc)(void);
class GUIButton : public GUIObject {
private : void (*clickFunc)(void);
public : void setClickFunction(ptr2clickFunc clickFunc);
};
GUIButton.cpp
void GUIButton::setClickFunction(ptr2clickFunc clickFunc)
{
this->clickFunc = clickFunc;
}
EntityToolGUI.h
class EntityToolGUI {
public : EntityToolGUI();
protected : void addAnimation();
}
EntityToolGUI.cpp
void EntityToolGUI::addAnimation()
{
cout<<"add animation"<<endl;
}
EntityToolGUI::EntityToolGUI()
{
....
btnAddAnimation->setClickFunction(&EntityToolGUI::addAnimation);
}
I am getting an error no matching function call to GUIButton::setClickFunction(void (EntityToolGUI::*)())
candidate is void GUIButton::setClickFunction(void (*)())
How do I solve this ?
Most (decent) C code that passes function pointers around use an extra void* argument for passing user context to the function. This is not so common in C++ (as better techniques than function pointers exist), but if you're stuck using function pointers for some reason then it may be appropriate.
typedef void (*ptr2clickFunc)(void*);
class GUIButton : public GUIObject {
private : ptr2clickFunc clickFunc;
private : void * userdata;
public : void setClickFunction(ptr2clickFunc clickFunc, void* userdata);
};
class Foo
{
static void do_foo( void * userdata )
{
Foo* thisptr = static_cast<Foo*>(userdata);
thisptr->foo();
}
void foo() { ... }
};
int main()
{
Foo foo;
GUIButton button;
button.setClickFunction( &Foo::do_foo, &foo );
button.click();
}
EDIT As noted by Bartek, if you're doing this a lot you can extract the static function into a template - it looks a bit like this (untested and probably with minor errrors).
// GUIButton is as before
// Note no static function here
class Foo { void foo(); }
template<typename T, void(T::*FN)() >
void Call( void * data)
{
static_cast<T*>(data)->*FN();
}
int main()
{
Foo f;
GUIButton button;
button.setClickFunction( &Call<Foo,&Foo::foo>, &f );
button.click();
}
If you want to pass obj fun ptr you can use boost::bind and boost::function
http://www.boost.org/doc/libs/1_50_0/libs/bind/bind.html
You cannot pass a pointer to non-static member function as a pointer to a "regular" non-member function. You should either make addAnimation static, or make ptr2clickFunc typedef a pointer to member function.
Note that invoking a pointer to member function is different from invoking a function pointer, because you must supply an instance on which the member pointer is to be invoked.
addAnimation needs to be static function. When the call back function is set the way you are doing it now, the object of class EntityTollGUI is not registered along with the function.
Try this one (C++11):
#include <stdio.h>
#include <stdlib.h>
#include <functional>
class Raiser
{
public:
std::function<void(int)> ev1, ev2;
void RaiseEv1()
{
if (!ev1._Empty())
ev1(44);
}
void RaiseEv2()
{
if (!ev2._Empty())
ev2(66);
}
};
class Handler
{
private:
int id;
std::function<void(int)> h;
public:
Handler(int newId)
{
id = newId;
h = [this](int i)
{
printf("Handler with id = %d captured event!\n", this->GetId());
};
}
void Hook1(Raiser & raiser)
{
raiser.ev1 = h;
}
void Hook2(Raiser & raiser)
{
raiser.ev2 = h;
}
int GetId()
{
return id;
}
};
int main(int argc, char * argv[])
{
Raiser raiser;
Handler handler1(1), handler2(2);
handler1.Hook1(raiser);
handler2.Hook2(raiser);
raiser.RaiseEv1();
raiser.RaiseEv2();
getchar();
}
AFAIK, this is the most you can get with events in C++ without using language extensions.

Passing function name as parameter of Another function in C++ class

I have two classes A and B. I want to pass a function name in class A as parameter of function in Class B. I tried with below sample, Is it correct way.
class A
{
public:
B m_b;
void MyFun()
{
// do something
}
void Test()
{
m_b.Process( MyFun );
}
}
class B
{
public:
void Process( void (*f)() )
{
(*f)();
}
}
thanks in advance
Since MyFun is a member function of class A, you need a pointer-to-member instead of a regular function pointer, and you also need an instance of class A to invoke the function on:
class B
{
public:
void Process(A *obj, void (A::*f)() )
{
(obj->*f)();
}
}
Actually, if MyFun is not a static member of your class, it has a hidden argument that is of type A*, so this is implemented like: m_a.MyFun(...) =~ MyFunImpl(&m_a, ...).
So, What you want is probably have a static function MyFun (you can't use this inside it), and inside B::Process call f().
If you need to pass this, refer to casablanca's answer (pointers to member functions).
Otherwise, if you want to pass an argument, you can lookup std::bind or lambda functions (C++0x), or boost::bind prior to that.
Follow the advice here: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.4, you'll end up with this:
class A;
typedef void (A::*MemFun)();
class B
{
public:
void Process(A& a, MemFun mf)
{
(a.*mf)();
}
};
class A
{
public:
B m_b;
void MyFun()
{
// do something
}
void Test()
{
MemFun p = &A::MyFun;
A a;
m_b.Process(a, p);
}
};

Converting method signatures

typedef void (__thiscall* LPVOIDPROC) (void);
class ClassA
{
LPVOIDPROC m_pProc;
void SetProc(LPVOIDPROC pProc) { m_pProc = pProc; }
void OnSomeEvent() { m_pProc(); }
}
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
pCA->Set((LPVOIDPROC)&ClassB::Proc); // error C2440
}
}
How to get rid of this error C2440: 'type cast' : cannot convert from 'void (__thiscall ClassB::* )(void)' to 'LPVOIDPROC' ? I don't want to limit LPVOIDPROC signature to ClassB only. This should be any class and referenced proc should not be static.
Workaround:
typedef void (* CLASSPROC) (void *);
template<class T, void (T::*proc)()>
void class_proc(void * ptr)
{
(static_cast<T*>(ptr)->*proc)();
}
class ClassA
{
CLASSPROC m_pProc;
void * m_pInstance;
public:
void SetProc(void *pInstance, CLASSPROC pProc) {
m_pInstance = pInstance;
m_pProc = pProc;
}
void OnSomeEvent() { m_pProc(m_pInstance); }
};
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
pCA->SetProc(this, class_proc<ClassB, &ClassB::Proc>);
}
};
I refer you to this link. Your type LPVOIDPROC is a pointer-to-function, which is not the same thing as a pointer-to-member-function. When you try to cast ClassB::Proc, you are trying to convert a pointer-to-member-function, an invalid operation.
You should take a look at boost::function, that offers exactly what you are looking for. Or you could use functors to encapsulate your functions if you don't want to resort to boost. Example:
struct VoidProcFunctor {
virtual void call() = 0;
};
class ClassB;
struct BProcFunctor : VoidProcFunctor {
BProcFunctor(ClassB* b) : b_(b) {}
void call();
private:
ClassB* b_;
}
class ClassA
{
public:
VoidProcFunctor* m_pProc;
void SetProc(VoidProcFunctor* pProc) { m_pProc = pProc; }
void OnSomeEvent() { m_pProc->call(); }
};
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
// warning! this is not the best design possible
BProcFunctor* bproc = new BProcFunctor(this);
pCA->SetProc(bproc);
}
};
void BProcFunctor::call() { b_->proc() }
Non-static methods require a 'this' pointer, without a 'this' pointer you cannot call it, and so it makes no sense to cast it to a C function pointer.
Consider making a simple class (let's call it X) that has
a data member that refers to a ClassB instance
a () operator (although I prefer methods with clear names) calling ClassB::Proc using the ClassB instance as this-pointer.
Instead of passing a function pointer to class A, make an instance of X (with its datamember to ClassB filled in) and pass this to class A.
Instead of calling a function pointer class A should call x().
Class X could even be written using templates, so if you have this situation for more than one class you must only write it once.
I think that in C# it can be done cleaner using delegates but I leave that to the C# and .Net specialists.
Never cast function pointers. You can end up with stack corruption. Don't do it.
Don't pass pointers to non-static member functions. They use a different calling convention and are not compatible.
In your case, making "Proc()" static might solve the problem.
You need your Proc method to be a static method.