我有基础类和派生类。 他们有一个虚拟功能 - 虚拟空行动() 我怎样才能将它传递给* pthread_create()*函数?
示例(有错误):
class Base{
protected:
pthread_t tid;
public:
virtual void* action() = 0;
};
class Derived : public Base{
void* action();
Derived(){
pthread_create(&tid, NULL, &action, NULL);
}
};
也许它应该是静态的? 我尝试了很多组合,但无法找到解决方案..
答案 0 :(得分:4)
几个月前,我在我的高级设计项目上遇到了这个问题。它需要一些基础C ++机制的知识。
潜在的问题是指向函数的指针与指向成员函数的指针不同。这是因为成员函数具有隐式的第一个参数this
。
来自man
页面:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
线程入口点是void* (*)(void*)
。您的函数Base::action
的类型为void* (Base::*)()
。丑陋类型声明的Base::
部分表示this
的类型。类型差异是编译器不接受您的代码的原因。
我们需要解决两件事才能使其发挥作用。我们不能使用成员函数,因为指向成员函数的指针不会将this
绑定到实例。我们还需要一个void*
类型的参数。值得庆幸的是,这两个修复是齐头并进的,因为解决方案是明确地自己传递this
。
class Base {
public:
virtual void* action() = 0;
protected:
pthread_t tid;
friend void* do_action(void* arg) {
return static_cast<Base*>(arg)->action();
}
};
class Derived : public Base {
public:
Derived() {
// This should be moved out of the constructor because this
// may (will?) be accessed before the constructor has finished.
// Because action is virtual, you can move this to a new member
// function of Base. This also means tid can be private.
pthread_create(&tid, NULL, &do_action, this);
}
virtual void* action();
};
修改: Woops,如果tid
为protected
或private
,则do_action
必须为friend
。< / p>
答案 1 :(得分:3)
你必须有一个函数,它将一个void指针传递给pthread_create
。我自己编写函数,作为一个函数,它指向Base
(Derived
也可以工作),然后调用参数的action
函数。然后,您可以创建一个运行该函数并收到this
作为参数的线程:
void *f(void *param)
{
Base* b = (Base *)param;
return b->action();
}
class Derived : public Base{
void* action();
Derived() {
pthread_create(&tid, NULL, f, this);
}
};
答案 2 :(得分:2)
确实必须是静态的。您还需要将对象作为参数传递给pthread_create:
void *Base::static_action(void *v)
{
((Base*)v)->action();
return NULL;
}
pthread_create(&tid, NULL, &Base::static_action, myObject);
答案 3 :(得分:1)
我通常会做类似的事情,我会让你填写其他细节(错误处理,锁定等):
开始方法:
bool pthreadBase::start()
{
return pthread_create(&threadID, NULL, &execute,this);
}
静态void *执行方法:
void *pthreadBase::execute(void *t)
{
reinterpret_cast<pthreadBase *> (t)->processLoop();
return NULL;
}
之后,您可以创建一个名为processLoop的虚方法,它将充当您的线程的入口点。
这是一个简单的实现(未测试):
class theThread: public pthreadBase
{
public:
theThread(SharedMemoryStructure *SharedMemory)
{
_Running = start();
_Shared = SharedMemory;
}
~theThread()
{
stop(); //Just do a join or something
_Running = false;
}
private:
void processLoop()
{
while(_Shared->someQuitFlag() == false)
{
/*Do Work*/
}
}
private:
bool _Running;
SharedmemoryStructure *_Shared;
};
答案 4 :(得分:0)
让它保持静态并不能保证工作,但实际上至少在大多数实现方面都有效(并且有足够的人依赖它,我很快就会看到这种变化,我会感到有些惊讶)。