关于在 C++ 中的函数指针,类成员函数和全局函数有什么区别?我问这个问题是因为 Windows 的 CreateThread 方法似乎不接受作为线程代码的函数如果是一个类成员。当该函数是全局方法时,我可以将其传递给 CreateThread 消息,但一旦我将其作为类的成员,就会出现错误“类型为 [方法布局] 的参数与类型为 LPTHREAD_START_ROUTINE 的参数不兼容”。现在 ClassName::* 在中间,这是否影响了它?
如何解决这个问题?
如何解决这个问题?
成员函数指针(DWORD(WINAPI Foo::*)(LPVOID)
)与函数指针(DWORD(WINAPI *)(LPVOID)
)是不同的类型。成员函数有一个隐藏的this
参数,导致签名不匹配。
最简单的方法是使用C++11的<thread>
头文件:
struct Foo {
void threadProc() {}
};
int main() {
Foo foo;
std::thread t{&Foo::threadProc, foo, /*other arguments to threadProc*/};
t.join();
}
CreateThread
,请利用void *
参数传递实例:struct Foo {
DWORD threadProc() {...}
};
extern "C" DWORD WINAPI proxyThreadProc(LPVOID userData) {
auto foo = static_cast<Foo *>(userData);
if (foo) {foo->threadProc();}
}
int main() {
Foo foo;
CreateThread(..., proxyThreadProc, &foo, ...);
}
现在你的类可以是任何你想要的类型(例如 std::function
),只要在代理过程中使用正确的参数调用即可正常工作。
proxyThreadProc
是Foo
类的静态成员函数,这种方法也同样适用。在这种情况下,有时使用私有成员函数是一个不错的方法。 - Magnus Hoffextern "C"
。尽管类静态函数通常使用与C函数相同的调用约定,它可能被认为是一个静态函数在类中工作。然而,这样做等于在等待错误发生(请参见下面的评论),因此请不要这样做——请改用 extern "C"
包装器。”(有趣的讨论主题) - Magnus Hoff是的,正如@chris所说,这里有一个隐藏的指针,它将连接参数的末尾。当线程执行时,它不知道要与最后一个参数位置上的指针匹配,然后在完成时无法恢复此函数的堆栈,因此除了全局函数或类的静态成员函数之外,禁止使用非静态成员函数来驱动线程函数。
CreateThread
所使用的函数指针不兼容。 - christhread([this]{member();})
,而不是正确答案中的胡言乱语,具有可移植性作为奖励。 - Mike Seymour