【发布时间】:2019-09-19 20:45:47
【问题描述】:
为了实现一个线程类(在C++98和Windows.h中)。我有这样的事情:
Thread::Thread(_beginthreadex_proc_type fn)
{
m_raw = fn;
m_args = 0;
m_handle = 0;
m_id = 0;
}
上面的代码可以正常工作,它接受一个不接收参数的函数,并且在下一个代码中,它的函数被一个新线程调用:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, m_raw, (m_args ? m_args : 0), 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
此代码也适用于不带任何参数的函数。 现在我的问题是我如何在 C++98 中接收我的构造函数中的可变参数并保存它们。 NO 如果我不需要帮助,我就不能使用现代 C++。所以请不要给我用 c++11 或更高版本实现的解决方案。
更新
现在我正在尝试一种 Java 风格的解决方案,因为每个线程都是一个 IRunnable,它有一个名为 Run 的纯虚函数。而线程几乎就是这个实现与抽象类的差异。通过这种方式,我可以避免参数,因为我不传递函数,而是编写另一个从 Thread 继承并实现 Run 的类。 代码如下:
界面
struct IRunnable
{
virtual void Run() = 0;
};
线程类
class Thread : public IRunnable
{
HANDLE m_handle;
DWORD m_id;
typedef unsigned (__stdcall *Function)(void*);
_beginthreadex_proc_type m_raw;
void* m_args;
public:
Thread();
~Thread();
Thread(_beginthreadex_proc_type, void*);
Thread(_beginthreadex_proc_type);
unsigned GetId();
virtual void Run() = 0;
void Join();
unsigned int __stdcall call(void*);
};
Call only 是调用 Run 函数成员的包装器
unsigned int __stdcall Thread::call(void* data)
{
Run();
return 0;
}
我的问题在这里:
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, &this->call, 0, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
当我在 vs2019 中编译时,上面的代码会产生下一个错误:
error C2276: '&': illegal operation on bound member function expression
error C2660: '_beginthreadex': function does not take 5 arguments
【问题讨论】:
-
为什么你想要构造函数的可变参数?您将如何处理这些论点以及您期望什么样的论点?
-
有很多方法,但没有一个好玩。与其经历那种痛苦,不如直接使用
boost::thread?它与 C++98 兼容,并且现代 C++ 的线程库以它为模型,因此稍后升级代码以使用<thread>非常简单。 -
我不能使用外部库是出于教育目的。谢谢
-
通过存储可变参数可以达到什么目的?它们没有名称,难以使用,没有类型信息,编译器对它们的支持非常有限......相反,您可以将 void* 存储到某些用户定义的结构中,或者用户传递一个实现 operator() 并使用其成员的函子对象。
-
把你需要的一切都放在一个结构中,并在你创建它的时候把它交给线程