我创建了一个新对象,并设置了一个数据和回调:
class DownloadData
{
std::function<void(int, bool)> m_callback;
int m_data;
public:
void sendHttpRequest()
{
// send request with data
}
private:
void getHttpResponse(int responseCode)
{
if (responseCode == 0)
{
// save data
m_callback(responseCode, true);
delete this;
return;
}
// some processing here
if (responseCode == 1 && some other condition here)
{
m_callback(responseCode, false);
delete this;
return;
}
}
}
现在用法 - 我创建了一个新对象:
if (isNeededToDownloadTheFile)
{
DownloadData* p = new DownloadData(15, [](){});
p->sendHttpRequest();
}
但是你可以看到https://isocpp.org/wiki/faq/freestore-mgmt#delete-this自杀是非常不可取的。是否有良好的设计模式或方法?
答案 0 :(得分:1)
如果你想删除该函数,唯一的方法是以某种方式存储对象。但是,这会引发所有权问题:谁是异步http请求的所有者,它应该调用回调?
在这种情况下,执行GCs作业实际上使代码非常清晰。但是,如果你想让它更适应C ++,我可能会选择类似于std::async
的类似承诺的界面。这样,同步代码路径可以更容易地存储promise对象。
你问了一个代码示例,所以有:
典型方法如下:
{
DownloadData* p = new DownloadData(15, [](auto data){
print(data)
});
p->sendHttpRequest();
}
数据可用后,即可打印。但是,您可以从另一端&#34;:
查看问题&#34;{
Future<MyData> f = DownloadData(15).getFuture();
// now you can either
// a) synchronously wait for the future
// b) return it for further processing
return f;
}
一旦请求实际处理, f
将保留实际值。这样你就可以将它推送到常规值,一直到实际需要该值的地方,并在那里等待它。当然,如果你异步使用它,你也可以为它生成另一个异步动作。
我认为,Future
的实现超出了本答案的范围,但在网上可以获得大量资源。承诺和期货的概念不是C ++特有的东西。
答案 1 :(得分:1)
你可以将它们放在vector
或list
中,getHttpResponse()
设置一个标志而不是delete this
完成后再设置一个标志,然后再设置另一部分代码偶尔遍历列表寻找已完成的请求。
这也可以让你实现超时。如果请求未在一天内返回,则可能不会发送,您应该删除该对象。
答案 2 :(得分:0)
如果调用者保留对下载对象的引用,那么它可以在下载信号结束时将其擦除:
class DownloadData
{
// true until download stops (atomic to prevent race)
std::atomic_bool m_downloading;
int m_data;
std::function<void(int, bool)> m_callback;
public:
DownloadData(int data, std::function<void(int, bool)> callback)
: m_downloading(true), m_data(data), m_callback(callback) {}
void sendHttpRequest()
{
// send request with data
}
// called asynchronously to detect dead downloads
bool ended() const { return !m_downloading; }
private:
void getHttpResponse(int responseCode)
{
if (responseCode == 0)
{
// save data
m_callback(responseCode, true);
m_downloading = false; // signal end
return;
}
// some processing here
if(responseCode == 1)
{
m_callback(responseCode, false);
m_downloading = false; // signal end
return;
}
}
};
然后从来电者那边:
std::vector<std::unique_ptr<DownloadData>> downloads;
// ... other code ...
if (isNeededToDownloadTheFile)
{
// clean current downloads by deleting all those
// whose download is ended
downloads.erase(std::remove_if(downloads.begin(), downloads.end(),
[](std::unique_ptr<DownloadData> const& d)
{
return d->ended();
}), downloads.end());
// store this away to keep it alive until its download ends
downloads.push_back(std::make_unique<DownloadData>(15, [](int, bool){}));
downloads.back()->sendHttpRequest();
}
// ... etc ...