在 C++ 中传递函数指针
Posted
技术标签:
【中文标题】在 C++ 中传递函数指针【英文标题】:Passing function Pointers in C++ 【发布时间】:2010-09-29 00:21:07 【问题描述】:我想做这个简单的代码工作。
#include <iostream>
#include <windows.h>
void printSome (int i)
std::cout << i << std::endl;
void spawnThread (void (*threadName)(int i))
CreateThread
(
0, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE)threadName, // thread function name
(LPVOID)i, // argument to thread function
0, // use default creation flags
0 // returns the thread identifier
);
int main ()
spawnThread(printSome(155));
我在windows上,使用vs。任何帮助都会非常感激。
【问题讨论】:
那么到底是什么问题? 【参考方案1】:CreateThread 需要 2 个参数:指向要作为线程执行的函数的指针,以及将提供给线程的 DWORD 参数。您的 spawnThread() 函数只有 1 个参数(threadName);你认为它有 2 个参数,因为“i”,但这确实是“threadName”类型定义的一部分。 (您也可以省略“i”;也就是说,您不需要将参数命名为“threadName”。)
无论如何,鉴于您需要 2 个参数,请重新定义 spawnThread:
void spawnThread(void (*threadEntryPoint)(int), int argument)
CreateThread(0,0,
(LPTHREAD_START_ROUTINE)threadEntryPoint,
(LPVOID)argument,
0,0);
注意我没有命名 threadEntryPoint 的 int 参数;告诉编译器该函数必须有一个 int 参数就足够了。
然后调用它:
spawnThread(printSome, 155);
无论如何,又快又脏,这会做你想做的。
第一次。
赖利。
【讨论】:
【参考方案2】:就个人而言,我不会考虑像您尝试做的那样传递函数指针,就像 C++ 一样。那就是用 C++ 编写 C 代码
相反,我会将它封装在一个类中。最大的优势是您可以重写该类以拥有您想要的任意数量的成员,而不必每次都执行油腻的转换技巧来获取您的参数。
代码有点啰嗦,所以我把它推到最后。但它让你做的是这样的事情:
class print_some : public basic_thread
private:
int i;
public:
print_some (int i) : i(i) ;
action_callback ()
std::cout << i << std::endl;
int main ()
print_some printer (155);
以下是我们其中一个类的一些摘录示例代码:
class basic_thread :
public:
basic_thread();
protected:
unsigned long m_ThreadId;
virtual void action_callback () ;
// Internal routine used to bridge between OS callback format and
// action_callback. *Must* be static for the OS.
static unsigned long __stdcall self_calling_callback (void *parameter);
...在 .cpp 中:
unsigned long __stdcall basic_thread::self_calling_callback (void *parameter)
if (parameter)
basic_thread * thread = reinterpret_cast<basic_thread *>(parameter);
thread->action_callback();
return 0; // The value returned only matters if someone starts calling GetExitCodeThread
// to retrieve it.
basic_thread::basic_thread ()
// Start thread.
m_Handle = CreateThread(NULL,
0,
self_calling_callback,
(PVOID)this,
0,
&m_ThreadId );
if( !IsHandleValid() )
throw StartException("CreateThread() failed", GetLastError());
【讨论】:
【参考方案3】:你不能在函数指针中传递参数信息;它必须单独通过。这正是 CreateThread 函数提供 void* 参数的原因,该参数可以指向您想要的任何内容。
此外,对于 C++ 应用程序,您应该 use _beginthread instead of CreateThread。
最后,您的程序很可能在线程运行之前终止。因此,您必须要么进入无限循环,要么使用 API 调用等待线程完成。
以下是使用WaitForSingleObject 阻塞直到线程完成的工作版本。
#include <iostream>
#include <process.h>
#include <windows.h>
void
printSome(int i)
std::cout << i << std::endl;
HANDLE
spawnThread(void (*threadName)(int), int i)
return (HANDLE) _beginthread((void (*)(void*)) threadName, 0, (LPVOID) i);
int
main(int argc, char *argv[])
HANDLE threadHandle;
threadHandle = spawnThread(printSome, 155);
WaitForSingleObject(threadHandle, INFINITE);
return 0;
这里有一个更 C++/面向对象的方式来处理同样的情况:
#include <iostream>
#include <process.h>
#include <windows.h>
class Thread
static void proxy(void *arg) (*(reinterpret_cast<Thread *> (arg)))();
HANDLE thread_;
public:
virtual ~Thread()
virtual void operator()() = 0;
void start() thread_ = (HANDLE) _beginthread(Thread::proxy, 0, this);
void waitForExit() WaitForSingleObject(thread_, INFINITE);
;
class Printer : public Thread
int i_;
public:
Printer(int i) : i_(i)
void operator()() std::cout << i_ << std::endl;
;
int
main(int argc, char *argv[])
Printer p(155);
p.start();
p.waitForExit();
return 0;
【讨论】:
很好的答案 - 除非您应该使用 _beginthread() 或 _beginthreadex() 而不是 CreateThread()。有关详细信息,请参阅***.com/questions/331536/…。 没错,我更新了答案。有太多的事情要解决! ;)【参考方案4】:正如这里很多人已经提到的,你不能在一个参数中传递一个函数指针和它应该被调用的参数。
你的线路
spawnThread(printSome(155));
“应该”(在 DWIM 世界中)表示“在带有参数 155 的单独线程上调用 printSome”。然而,这不是 C++ 理解它的方式。 C++ 看到“将在 155 上调用的 printSome 的结果作为参数传递给 spawnThread”。换句话说,步骤的顺序是:
以 155 作为参数调用 prinotSome。将其存储在临时内存中。 以临时内存的内容作为参数调用 spawnThread。为了做到你真正的意思,你必须幽默 C++ 并将参数与函数分开。如何做到这一点已经在其他答案中解释过。简称:
callOnOtherThreadWithArgument(函数,整数);
【讨论】:
【参考方案5】:您可以在此处阅读您的操作方法:http://www.newty.de/fpt/fpt.html
2.6 如何将函数指针作为参数传递?
您可以将函数指针作为 函数的调用参数。你需要 例如,如果您想通过 指向回调函数的指针。这 以下代码显示了如何通过 指向返回一个函数的指针 int 并接受一个浮点数和两个字符:
//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer
// <pt2Func> is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
int result = (*pt2Func)(12, 'a', 'b'); // call using function pointer
cout << result << endl;
// execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
void Pass_A_Function_Pointer()
cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
PassPtr(&DoIt);
【讨论】:
以上是关于在 C++ 中传递函数指针的主要内容,如果未能解决你的问题,请参考以下文章