I just wanted to ask if my approach is wrong or one is the right way and it can be done.
In the project, I have one hal and several types of Dir based on Base. When I create some dir I pass hal to it because each dir uses it in its own way. Everyone also reacts in their own way to events in the hal. so I wanted to use the callback mechanism. I one moment I have only one specific controller, and I change it, delete, and create another, at this moment I must connect callback. I create a solution with one dir type, and it's working fine. But what path choose when I want to use a few different dir, Can I cast to base and use base in Hal something like this:
class Base;
class Hal
{
public:
void set_callback(void (Base::*callback)(int), Base* base)
{
m_callback = callback;
m_base = base;
}
void fun()
{
(m_base->*m_callback)(some_int);
}
private:
Base* m_base;
void (Base::*m_callback)(int);
};
#include "Hal.h"
class Base
{
public:
virtual void active() = 0;
virtual void foo(int variable) = 0;
};
class Dir : public Base
{
public:
Dir(Hal& hal)
: m_hal(hal)
{}
void active()
{
auto callback = &Dir::foo;
//add some casting?
m_hal.set_callback(callback, this);
}
void foo(int variable)
{
// some code
}
private:
Hal& m_hal;
};
Maybe I should add a separate class for routing such callbacks? Or use a different mechanism? Unfortunately, I don't have functional lib available in this project /:
CodePudding user response:
Member function pointers for one class are not convertible to member function pointers of another class, even if the functions look compatible. You can approximate this conversion using a layer of abstraction, for example using a std::function<void(Base*, int)>
but it cannot be achieved using a cast.
However, member function pointers respect polymorphism. The actual function being called will depend on the dynamic type of the object with which it is called.
You only need to pass &Bar::foo
, which is virtual
. Since it will be called with a Dir
the Dir::foo
override will be used.
Changing to m_hal.set_callback(&Bar::foo, this);
should do what you want.
Live example : https://godbolt.org/z/fd8hsbanv