gpt4 book ai didi

c++ - 在回调函数中安全地删除调用者对象

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:43:05 25 4
gpt4 key购买 nike

库中的代码段:

class Client{
public:
class CallBack {
public:
virtual void onData(Client* caller, std::string& data) =0;
};

Client(CallBack* callback):m_callBack(callback){}
virtual ~Client(){}
void onData(std::string data) {
m_callBack->onData(this, data);
m_totalDataVol += data.size();
}

private:
CallBack* m_callBack;
int m_totalDataVol = 0;
}

来自应用程序的代码段:

class AppHandler: public Client::Callback {
void onData(Client* caller, std::string& data) {
/* Some complex logic and check certain conditions*/
delete caller; // Application will crash, due to
// accessing member of deleted object (m_totalDataVol)
}
}

此外Caller对象(Client类的实例)为应用程序所有,应用程序没有限制删除它。

我该如何克服这个问题?

非常复杂的场景:基础库的 Client 类可以由另一个库(ClientEx 类)扩展,应用程序可能会使用该扩展库(不是基础库)

最佳答案

让你的回调返回一个 bool 指示调用者是否应该删除自己。不要从回调中删除客户端。

此外,如果 data.size == 0,是否还需要调用回调? Client 可以在调用回调之前检查此条件,并删除自身(或以其他方式适本地处理它)。

如果仍然需要调用回调,也许您可​​以通过在调用后检查客户端中的条件来避免更改返回类型:

void onData(std::string data) {
m_callBack->onData(this, data);
if (data.size() != 0) {
m_totalDataVol += data.size();
}
else {
delete this;
}
}

或者,如果您真的必须允许回调来删除客户端,那么您需要某种方式来跟踪客户端何时被删除,您可以在客户端本身中使用这种方式。这意味着保留对另一个对象的引用:

class Client{
public:
class CallBack {
public:
virtual void onData(Client* caller, std::string& data) =0;
};

Client(CallBack* callback):m_callBack(callback){}, was_deleted(nullptr)
virtual ~Client(){
if (was_deleted) *was_deleted = true;
}
void onData(std::string data) {
bool *was_deleted = new bool();
this->was_deleted = was_deleted;
m_callBack->onData(this, data);
if (! *was_deleted) {
m_totalDataVol += data.size();
this->was_deleted = nullptr;
}
delete was_deleted;
}

private:
CallBack* m_callBack;
int m_totalDataVol = 0;
// When issuing a callback, holds a pointer to a flag that can
// be used to track if this object has been deleted:
bool * was_deleted;
}

(请注意,上面的解决方案不是线程安全的,但可能会如此。另请注意,上面的代码无法编译,就像您问题中的示例代码一样 - 我已经尝试匹配源代码尽可能多,原则应适用于实际代码)。

关于c++ - 在回调函数中安全地删除调用者对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32472221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com