DISCLAIMER I DO NOT USE BOOST
OR OTHER LIBRARIES
Finally I've learned how PointerToMemberFunction works. This is my example code.
#include <iostream>
using namespace std;
class Foo
{
public:
void foo ( )
{
cout << "I'm a foo method\n";
};
};
class Bar
{
public:
void bar ( Foo* fooPtr , void(Foo::*fooFnPtr)() )
{
(fooPtr->*fooFnPtr)();
};
};
int main()
{
Foo* foo = new Foo();
Bar* bar = new Bar();
bar->bar ( foo , &Foo::foo );
return 0;
}
Now, what the problem is. Bar::bar
must be modified somehow, because in real project it won't know, what class fooFnPtr
is a pointer to. In other words Bar::bar
must work with any class, not only with Foo
. I won't know, a pointer to an instance of what class is passed to Bar::bar
.
The one thing which can help is that all classes which will work with Bar::bar
are children of one class!
Is this achievable and how? How do i fix my code? Thanks in advance!
You could make bar
a template function:
template<class T>
void bar ( T* fooPtr , void(T::*fooFnPtr)() )
{
(fooPtr->*fooFnPtr)();
}
Of course, if you only want to pass pointers to members that exist in the common base class, you can simply do this:
#include <iostream>
using namespace std;
class Foo
{
public:
virtual void foo ( )
{
cout << "I'm a foo method\n";
};
};
class Derived: public Foo
{
public:
virtual void foo ( )
{
cout << "I'm a Derived method\n";
};
};
class Bar
{
public:
void bar ( Foo* fooPtr , void(Foo::*fooFnPtr)() )
{
(fooPtr->*fooFnPtr)();
}
};
int main()
{
Derived* derived = new Derived();
Bar* bar = new Bar();
bar->bar ( derived , &Foo::foo );
return 0;
}
I guess you are after closures and delegates, or the equivalent in C++. In short, they are instances that can be called, and that contain both the pointer to your class instance (or the instance itself) and the pointer to the method there.
Take a look to std::bind. They normally return cryptic instances of template classes, that are all convertible to std::function<...>, in case you need to use an uniformly-typed argument as parameter of a function or method.
So, your code would look like this:
void Bar::bar(std::function<void()> f)
{
....
}
Foo* foo = new Foo();
Bar* bar = new Bar();
auto f = std::bind( &Foo::foo, foo);
bar->bar ( f );
Of course, if you have decided not to use any library, you might nonetheless take a look at how those libraries have solved the problem before, so that you can reinvent the wheel in the best possible way.