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

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);
}
};

Related

Passing non-static member function as argument to a member function in a different class

UPDATE I realize this question's lacking a proper MCVE, it will take me some time to come up with one. I will update it when I have time to come back to this, sorry. I appreciate the answers thus far.
Following this answer regarding static functions:
Declaration (in MyClass)
void MyClass::func ( void (MyOtherClass::*f)(int) ); //Use of undeclared identifier 'MyOtherClass'
Example of function being passed to func:
void MyOtherClass::print ( int x ) {
printf("%d\n", x);
}
Function call (in MyOtherClass)
void MyOtherClass::loop(){
func(&MyOtherClass::print);
}
How can one pass a member function as a parameter of a member function of another class?
According to the ISO, the answer is "don't". Unlike normal functions, a non-static member function is meaningless without an instance of the class. As a workaround, you can have your calling function take a std::function and pass it a lambda.
Example:
void calling_func(std::function<void()> f);
struct foo
{
void func();
void call()
{
calling_func([this]{
func();
});
}
};
can't you just use std::function and std::bind to that?
class MyOtherClass
{
public:
MyOtherClass() {}
void print(int x)
{
printf("%d\n", x);
}
};
class MyClass
{
private:
std::function<void()> CallbackFunc;
public:
MyClass() {};
void AssignFunction(std::function<void(int)> callback, int val)
{
CallbackFunc = std::bind(callback, val); //bind it again so that callback function gets the integer.
}
void DoCallback()
{
CallbackFunc(); //we can then just call the callback .this will, call myOtherClass::print(4)
}
};
int main()
{
MyClass myObject;
MyOtherClass myOtherObject;
int printval = 4;
//assign the myObject.callbackfunc with the myOtherClass::print()
myObject.AssignFunction(std::bind(&MyOtherClass::print, myOtherObject,std::placeholders::_1), 4);
//calling the doCallback. which calls the assigned function.
myObject.DoCallback();
return 0;
}

function pointer to a class member

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))
{
}
};

c++ Creating vector of function pointers in a given class, with function being a member of a different class

I am having a vector of function pointers in one class and to it i want to pass address of function in some other class. The following implementation gives errors. What is the correct way?
class A
{
public:
void func ()
{
}
};
class B
{
public:
std::vector<void(*)()) myVec;
void update_func()
{
myVec.push_back(&A::func);
}
};
int main()
{
B* b = new B;
b->update_func();
return 0;
}
A pointer to the non-static member function A::func doesn't have type void(*)(void), it has type void(A::*)(void). So either change the vector to match the elements that you want it to have, or else use a pointer to a function of the correct type for the vector.
A's func() has to be static to match the declaration of the function pointer. Meanwhile, it needs to be public such that it is accessible to class B.
update_func() in B also needs to be public since otherwise in main it is not accessible.
vector declaration has typo, it has to be vector<>, not vector<).
//
class A
{
public:
static void func ()
{
}
};
class B
{
std::vector<void(*)()> myVec;
public void update_func()
{
myVec.push_back(&A::func);
}
};
int main()
{
B* b = new B;
b->update_func();
return 0;
}
This code has many issues..
first b->func should have () after it if you want to call that function..
second.. what is void update func().. also bad code..
third you cannot use these functions since they are private...
you do however push it correctly into the vector...

How to pass a method as callback to another class?

I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...

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.