dimanche 17 décembre 2017

Creating a callback with std::function as class-member

I have designed a simple callback-keyListener-"Interface" with the help of a pure virtual function. Also I used a shared_ptr, to express the ownership and to be sure, that the listener is always available in the handler. That works like a charme, but now I want to implement the same functionality with the help of std::function, because with std::function I am able to use lambdas/functors and I do not need to derive from some "interface"-classes.

I tried to implement the std::function-variant in the second example and it seems to work, but I have two questions related to example 2: (No template-solutions please!)

  1. Why does this example still work, although the listener is out of scope? (It seems, that we are working with a copy of the listener instead of the origin listener?)

  2. How can I modify the second example, to achieve the same functionality like in the first example (working on the origin listener)? (member-ptr to std::function seems not to work! How can we handle here the case, when the listener is going out of scope before the handler? )

Example 1: With a virtual function

#include <memory>

struct KeyListenerInterface
{
    virtual ~KeyListenerInterface(){}
    virtual void keyPressed(int k) = 0;
};

struct KeyListenerA : public KeyListenerInterface
{
    void virtual keyPressed(int k) override {}
};

struct KeyHandler
{
    std::shared_ptr<KeyListenerInterface> m_sptrkeyListener;

    void registerKeyListener(std::shared_ptr<KeyListenerInterface> sptrkeyListener)
    {
        m_sptrkeyListener = sptrkeyListener;
    }

    void pressKey() { m_sptrkeyListener->keyPressed(42); }
};

int main()
{
    KeyHandler oKeyHandler;

    {
        auto sptrKeyListener = std::make_shared<KeyListenerA>();
        oKeyHandler.registerKeyListener(sptrKeyListener);
    }

    oKeyHandler.pressKey();
}

Example 2: With std::function

#include <functional>
#include <memory>

struct KeyListenerA
{
    void operator()(int k) {}
};

struct KeyHandler
{
    std::function<void(int)>  m_funcKeyListener;

    void registerKeyListener(const std::function<void(int)> &funcKeyListener)
    {
        m_funcKeyListener = funcKeyListener;
    }

    void pressKey() { m_funcKeyListener(42); }
};

int main()
{
    KeyHandler oKeyHandler;

    {
        KeyListenerA keyListener;
        oKeyHandler.registerKeyListener(keyListener);
    }

    oKeyHandler.pressKey();
}

Aucun commentaire:

Enregistrer un commentaire