Home > Software design >  Callback casting and set from another object [resolved]
Callback casting and set from another object [resolved]

Time:02-12

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

  • Related