#include <iostream>
#include <functional>
#include <memory>
class Event
{
public:
void RegisterHandler(std::function<void(bool)> handler)
{
mHandler = handler;
}
void Fire(bool value)
{
if (mHandler)
{
mHandler(value);
}
}
private:
std::function<void(bool)> mHandler;
};
class EventListener
{
public:
explicit EventListener(const std::string& value) : mValue{value}
{
std::cout << mValue << " constructor" << std::endl;
}
~EventListener()
{
std::cout << mValue << " destructor" << std::endl;
}
void Listen(Event& event)
{
event.RegisterHandler(std::bind(&EventListener::Handler, this, std::placeholders::_1));
}
private:
void Handler(bool value)
{
std::cout << mValue << " event " << value << std::endl;
}
std::string mValue;
};
int main()
{
{
Event event{};
auto handler {std::make_shared<EventListener>("first")};
handler->Listen(event);
event.Fire(true);
}
{
Event event{};
{
auto handler {std::make_shared<EventListener>("second")};
handler->Listen(event);
}
std::make_shared<std::string>("Hello from dangling pointer");
event.Fire(false);
}
}
Output:
first constructor
first event 1
first destructor
second constructor
second destructor
om dangling pointer event 0
std::enable_shared_from_this
seems to be a solution.
class EventListener : public std::enable_shared_from_this<EventListener>
{
public:
void Listen(Event& event)
{
event.RegisterHandler([sharedThis{shared_from_this()}](bool value)
{
sharedThis->Handler(value);
});
}
Output:
first constructor
first event 1
first destructor
second constructor
second event 0
second destructor
The two rules I am aware of:
- After capturing
this
make sure you remove/unregister/cleanup the capture in destructor. - Use
shared_from_this()
to don't bother about the lifetime.
Are there better solutions? Any advice how to prevent/handle such cases?
Aucun commentaire:
Enregistrer un commentaire