我有以下类结构用于管理具有不同原型的回调:
class MethodHandlerBase: public std::enable_shared_from_this<MethodHandlerBase>{
public:
virtual void operator()(void* data) = 0;
virtual ~MethodHandlerBase(){}
};
class MethodHandlerA: public MethodHandlerBase{
private:
MethodHandlerACallback cb;
public:
MethodHandlerA(MethodHandlerACallback cb): cb(cb){}
virtual void operator()(void* data);
};
class MethodHandlerB: public MethodHandlerBase{
private:
MethodHandlerBCallback cb;
public:
MethodHandlerB(MethodHandlerBCallback cb): cb(cb){}
virtual void operator()(void* data);
};
在某些情况下,MethodHandlera
或MethodHandlerb
可能在传递到别处的lambda表达式中使用this
(包装在shared_ptr),因此我需要确保在需要时正确删除它。 因此,我向基类添加了std::enable_shared_from_this
继承。
但是我读到,您通常不能通过继承使用std::enable_shared_from_this
(除了使用模板,模板实际上不再是继承)。 在我的理解,这是由于可能错误地破坏实例。 在这种情况下,我假设我的代码可以正常工作,因为它使用了虚拟析构函数(无论如何都需要它)。
那么,我的理论是正确的吗?还是关于std::enable_shared_from_this
继承,还有什么我不理解的地方?
编辑:
添加一个简短的例子,说明我打算如何使用它:
从班级内部:
void MethodHandlerB::operator()(void* data){
std::shared_ptr<MethodHandlerB> thisPtr = std::dynamic_pointer_cast<MethodHandlerB>(this->shared_from_this());
putLamdaToSomeGlobalEventThing([thisPtr](){
thisPtr->doSomething();
});
}
从外面
std::vector<MethodHandlerBase> vec{std::make_shared<MethodHandlerB>()};
一些小问题:
void MethodHandlerB::operator()(void* data){
auto thisPtr = std::static_pointer_cast<MethodHandlerB>(this->shared_from_this());
putLamdaToSomeGlobalEventThing([thisPtr = std::move(thisPtr)](){
thisPtr->doSomething();
});
}
this
和共享指针使用单独的捕获,这完全避免了强制转换:void MethodHandlerB::operator()(void* data){
putLamdaToSomeGlobalEventThing([this, thisPtr = shared_from_this()](){
doSomething();
});
}
enable_shared_from_this和shared_ptr调用运算符delete.
如果将基类用于具有虚拟析构函数的类型,运算符delete可以正常工作。