Here is the code, it's pretty straightforward.
class Foo
{
public:
void print()
{
std::cout<<"Foo::print\n";
}
};
Game::Game()
{
{
Foo foo;
player.onclick = bind(&Foo::print,foo);
}
player.onclick();
}
After the inner scope is done the foo object goes out of scope, but the print method is still called, I guess this happens because player holds a reference to the foo object? Is there a way to stop this from happening? I don't want objects to stay alive and receive events when they are supposed to be destroyed.
Thanks.
std::function
You are binding to a copy of foo
; that copy lasts as long as the bound function object, while the original foo
is destroyed at the end of its scope.
If you don't want to keep it alive, then bind to a pointer (&foo
) or a reference (std::ref(foo)
); and then you must be careful not to call the function object once foo
has gone out of scope. Note that there's no way to tell from the function object that this has happened; calling it will give undefined behaviour.
In order to safely disconnect the object when it's destroyed, you would have to either arrange for its destructor to reassign onclick
, or make some other object responsible for first reassigning onclick
, and then destroying the object.
And the print method is still getting called, wasn't what I was expecting - Barış Uşaklı 2012-04-04 20:01
foo
is destroyed will give undefined behaviour (In this case, that behaviour is likely to print the message, since the member function doesn't do anything with the dead object). If you need the function object to be safely invalidated, then you'll need to do that yourself somehow - Mike Seymour 2012-04-04 20:03
onclick
. The zombie flag won't work, since it will be destroyed along with the object. If you really want automatic invalidation, then you'll have to find a way to reassign onclick
from the object's destructor. A better solution might be to make some other object responsible for both destroying the object and disconnecting it from whatever it's been connected to - Mike Seymour 2012-04-04 20:13
Foo
class, and in destructor of Foo
, you can say to this container to set "zombie flag - Lol4t0 2012-04-04 20:17
void print() { std::cout<<"Foo::print\n"; } private: Player& player; };
Game::Game() {
{ Foo foo(player);
if(player.onclick) player.onclick();
}
if(player.onclick) player.onclick();
} - Barış Uşaklı 2012-04-04 20:34
onclik
signal of player
-class object. If this restriction is ok, this solution should wor - Lol4t0 2012-04-04 20:49
From your description it sounds like you actually want an event loop. While std::bind
is useful for something like that it isn't one all by itself. I suggest you have a look at boost.signals
I think you should use shared_ptr
when you assign Foo
to Player
, and keep a weak_ptr
to Foo
in Player
. Then try to lock the weak_ptr
in the onclick
function to see if Foo
is still alive. Something like this:
using namespace std;
class Foo
{
public:
void print()
{
cout<<"Foo::print\n";
}
};
class Player
{
public:
weak_ptr<function<void()>> _onClickFuntion;
void onclick()
{
shared_ptr<function<void()>> tempFunction(_onClickFunction.lock());
if (tempFunction)
tempFunction();
}
}
Game::Game()
{
{
Foo foo;
player._onClickFuntion = shared_ptr<function<void()>>(new bind(&Foo::print,foo));
}
player.onclick();
}