Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Polymorphic pointer to member functions

I'm not very good at C++ (but I'm familiar with OOP/Java), but I have to create a game for my C++ class. I want to setup a kind of game engine like that used for Flash games written in ActionScript.

I wrote this two classes, where Actor is meant as a base class (probably will be abstract) and Player should actually implement it.

The problem is that I want to avoid duplicate code in the functions addEventListener and handle and re-declaring _handlerMap, since I want to achieve data hiding and such things.

The problem, I guess, is that _eventMap should contain handler values that can change class Actor::*handler and Player::*handler. Is it possible?

    class Actor {
    protected:
        typedef void(Actor::*handler)(Event);
        map<int, handler> _handlerMap;
    public:
        virtual void addEventListener(int ID, handler h) {
            _handlerMap.insert(std::make_pair(ID, h));
        };
        virtual void handle(int ID) {
            handler h = _handlerMap[ID];
            Event e;
            if (h)
                (this->*h)(e);
        }
        virtual void onUpdate(Event e) {
            cout << "Actor::onUpdate()" << endl;
        };
    };

class Player : public Actor {
    typedef void(Player::*handler)(Event);
    map<int, handler> _handlerMap;
public:
    void addEventListener(int ID, handler h) {
        _handlerMap.insert(std::make_pair(ID, h));
    };
    void handle(int ID) {
        handler h = _handlerMap[ID];
        Event e;
        if (h)
            (this->*h)(e);
    }
    void onKeydown(Event e) {
        cout << "Player::onKeyDown()" << endl;
    };
};

I wish it was possible to declare Player as:

class Player : public Actor {
        typedef void(Player::*handler)(Event);
 public:
        void onWhateverEvent(Event e);
 }

I hope you understand.

like image 671
SimoneS93 Avatar asked Nov 03 '22 20:11

SimoneS93


1 Answers

You need something like this (not tested):

class Dispatcher {
  public:
    virtual void dispatchEvent(Event*) = 0;
};

template <class C>
class DispatcherImpl : public Dispatcher
{
    typedef void(C::*handler)(Event* e);
    std::map<int, handler> _handlerMap;
    C* _owner;
  public:
    DispatcherImpl (C* c) : _owner(c) {}
    addEventListener(int ID, handler h) {
        _handlerMap.insert(std::make_pair(ID, h));
    }        
    void dispatchEvent(Event*)
    {
      handler h = handlerMap[e->id];
      if (h) (_owner->*h)(e);
    }
}

Now let each type T of actor own a DispatcherImpl<T>, and you are all set. You may also have e.g. Player inherit from DispatcherImpl<Player>.

like image 57
n. 1.8e9-where's-my-share m. Avatar answered Nov 09 '22 05:11

n. 1.8e9-where's-my-share m.