为说明这个问题,让我们想象一个虚拟的示例,其中有一个来自外部API的函数:
// This function is run in a separated thread
void Transfert(string source, string destination, void (*callbackFunction)(int))
{
for(int i = 0; i < 100; i++)
{
// Simulation of a file transfert
// ...
//
// We call the callback function to update the progression of the file transfert
callbackFunction(i);
}
}
我想使用此函数传输文件,并在回调函数的帮助下跟踪进度。这是我的代码:
// Class containing information about the transfert
class FileTransfert
{
public:
FileTransfert(string, string);
void MyCallback(int);
// Those members are public to simplify this example but should be private
long m_progress;
string m_source;
string m_destination;
};
FileTransfert::FileTransfert(string source, string destination)
{
m_source = source;
m_destination = destination;
}
// Used to update the progress variable
void FileTransfert::MyCallback(int progress)
{
m_progress = progress;
}
int main(int argc, char* argv[])
{
FileTransfert f("source.txt", "destination.txt");
// It's a new thread
Transfert(f.m_source, f.m_destination, f.MyCallback); // Compilation error
// Now I want to follow the transfer with the m_progress variable
return 0;
}
我的班级FileTransfert
有一个m_progress
成员,我想在文件传输期间刷新它。因此,我创建了一个用于更新m_progress
的回调函数。
问题是我不能使用对象的方法作为回调函数。
所以,这是我的问题:如何修改代码以适应转移的进程?
我有一些限制:我必须从{{1} Transfert
类之外的函数,而FileTransfert
变量必须在m_progress
类之内。换句话说,我无法更改代码的所有体系结构。
重要说明:我无法更改FileTransfert
函数的代码和签名。在这两个问题(here和here)的答案中,我们更改了函数的签名,但我不能更改。
编辑
正如我在评论中所说,如果我不能更改Transfert
函数的签名,就没有适当的解决方案。一种想法是使用全局变量,但在多线程环境中可能会非常危险。