我有一个类foo
,它接受一个类bar
方法之一的成员函数指针,但是类吧可能比foo
的生命周期更短有没有一种方法可以使用Functor在执行之前可以检查bar
的存在吗?
目前,我正在尝试使用std::function
的{{1}}但没有成功。
bool operator
答案 0 :(得分:1)
我想不出任何简单的方法如何让Foo知道何时销毁回调对象,但如果你真的想从Foo类验证对象是否存活,我会在某处使用weak_ptr路。如果您通过new
创建Bar,则可以通过make_shared
创建实例,并且您可以执行类似的操作(在每次构建Bar实例后,额外的成本是一个函数调用):
class Bar;
class Foo
{
public:
void Foo::SetCallback( std::function< void( void ) > cb )
{
_cb = cb;
}
void Foo::RegisterBar(std::weak_ptr<Bar> inbarPtr)
{
barRef = inbarPtr;
}
void Foo::CallCallback()
{
if( _cb && !barRef.expired()) _cb();
}
private:
std::function< void( void ) > _cb;
std::weak_ptr<Bar> barRef;
};
class Bar
{
public:
Bar( Foo* _foo )
{
_foo->SetCallback( std::bind( &Bar::myCalledbackFunc, this ));
}
void myCalledbackFunc()
{
//do stuff
}
};
int main()
{
Foo fooInstace;
std::shared_ptr<Bar> barInstance = std::make_shared<Bar>(&fooInstace);
fooInstace.RegisterBar(barInstance);
return 0;
}
如果你真的坚持只对Bar类进行更改,你可以使用这个丑陋,丑陋的hack和一个空的自定义删除器:
class Bar;
class Foo
{
public:
void Foo::SetCallback( std::function< void( void ) > cb , std::weak_ptr<Bar> inbarPtr)
{
_cb = cb;
barRef = inbarPtr;
}
void Foo::CallCallback()
{
if( _cb && !barRef.expired()) _cb();
}
private:
std::function< void( void ) > _cb;
std::weak_ptr<Bar> barRef;
};
class Bar
{
std::shared_ptr<Bar> selfPtr;
public:
Bar( Foo* _foo )
{
selfPtr = std::shared_ptr<Bar>(this, Bar::EmptyDeleter);
_foo->SetCallback( std::bind( &Bar::myCalledbackFunc, this ), selfPtr);
}
void myCalledbackFunc()
{
//do stuff
}
protected:
static void EmptyDeleter(Bar*)
{
}
};
答案 1 :(得分:0)
在C ++中,对象使用的内存在销毁对象时不会归零。因此,Silvester Seredi在他的回答中提到任何指针都知道它引用的对象是否被破坏的唯一方法是指针引用一个拥有自动指针的对象。另外值得注意的是,对象不能在内部拥有,因此对象无法从根本上提供指示它是否已被破坏。
因此,唯一的解决方案是通过仿函数引用其成员的类被破坏,通知持有仿函数的类,如perreal所示。请注意,这不是多线程安全的。
class Foo
{
public:
void SetCallback( std::function< void( void ) > cb )
{
_cb = cb;
}
void UnSetCallback()
{
_cb = std::function< void( void ) >();
}
void CallCallback()
{
if( _cb ) _cb();
}
private:
std::function< void( void ) > _cb;
};
class Bar
{
public:
Bar( Foo* foo ) : _foo( foo )
{
_foo->SetCallback( std::bind( &myCalledbackFunc, this );
}
~Bar()
{
_foo->UnSetCallback();
}
void myCalledbackFunc()
{
//do stuff
}
private:
Foo _foo;
};