C++98如何处理多个不同类型的参数?
How to deal with multiple parameters of different types in C++98?
为了实现一个线程class(在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 风格的解决方案,因为每个线程都是一个 I运行nable,它有一个名为 运行 的纯虚函数。而线程几乎就是这个实现与抽象的差异 class。这样我可以避免参数,因为我不传递函数而不是我编写另一个继承自 Thread 并实现 运行 的 class。
代码如下:
界面
struct IRunnable
{
virtual void Run() = 0;
};
线程class
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*);
};
仅调用是调用 运行 函数成员的包装器
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
如果您查看几乎所有线程库,它们很少支持发送多个参数;你通常会发送一个指向某物的指针,如果你想要很多东西,你会创建一个包含很多东西的结构并发送一个指向它的指针。
但是,如果您真的想要这个,您可以使用 C 可变参数函数来遍历所有可变参数,并使用它们分配一个链表,或分配它们的数组,或您想要的任何其他数据结构。然后,将指向它的指针发送到您的线程入口函数。不过,您的函数仍然只需要一个指针。
在 C 中,没有简单的方法来构建 va_list,这就是发送可变参数的方式。您不能只发送主线程上的 va_list ,因为该内存在到达新线程时不会存在。也没有很好的方法来扩展 va_list 来填充函数参数。
顺便说一句,我知道你在使用 C++,但就 C++98 而言,它的可变参数支持与 C 中的基本相同,这就是我在回答中提到 C 的原因。
对于您编辑过的问题,出现编译错误的原因是您试图将地址发送到 Thread 对象的成员函数。您不能在不保留对象指针的情况下获取指向成员函数的指针并使用它们。相反,您应该创建一个以 Thread* 作为参数的全局函数,发送指向该函数的指针,并让它调用您的可运行对象。
unsigned thread_entry(void* thread_ptr)
{
Thread* thread = (Thread*) thread_ptr;
return thread->call();
}
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, thread_entry, this, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
P.S。如果问题明显不同,通常最好提出新问题而不是编辑旧问题。
为了实现一个线程class(在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 风格的解决方案,因为每个线程都是一个 I运行nable,它有一个名为 运行 的纯虚函数。而线程几乎就是这个实现与抽象的差异 class。这样我可以避免参数,因为我不传递函数而不是我编写另一个继承自 Thread 并实现 运行 的 class。 代码如下:
界面
struct IRunnable
{
virtual void Run() = 0;
};
线程class
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*);
};
仅调用是调用 运行 函数成员的包装器
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
如果您查看几乎所有线程库,它们很少支持发送多个参数;你通常会发送一个指向某物的指针,如果你想要很多东西,你会创建一个包含很多东西的结构并发送一个指向它的指针。
但是,如果您真的想要这个,您可以使用 C 可变参数函数来遍历所有可变参数,并使用它们分配一个链表,或分配它们的数组,或您想要的任何其他数据结构。然后,将指向它的指针发送到您的线程入口函数。不过,您的函数仍然只需要一个指针。
在 C 中,没有简单的方法来构建 va_list,这就是发送可变参数的方式。您不能只发送主线程上的 va_list ,因为该内存在到达新线程时不会存在。也没有很好的方法来扩展 va_list 来填充函数参数。
顺便说一句,我知道你在使用 C++,但就 C++98 而言,它的可变参数支持与 C 中的基本相同,这就是我在回答中提到 C 的原因。
对于您编辑过的问题,出现编译错误的原因是您试图将地址发送到 Thread 对象的成员函数。您不能在不保留对象指针的情况下获取指向成员函数的指针并使用它们。相反,您应该创建一个以 Thread* 作为参数的全局函数,发送指向该函数的指针,并让它调用您的可运行对象。
unsigned thread_entry(void* thread_ptr)
{
Thread* thread = (Thread*) thread_ptr;
return thread->call();
}
void Thread::Join()
{
m_handle = (HANDLE)_beginthreadex(0, 0, thread_entry, this, 0, 0);
if (m_handle) WaitForSingleObject(m_handle, INFINITE);
}
P.S。如果问题明显不同,通常最好提出新问题而不是编辑旧问题。