日期:2014-05-16  浏览次数:20805 次

线程的start_routine函数不能定义在class中么

有A.h和A.cpp文件,
-------------------------------
A.h 中
class{
public:
  int id;
  /*
  各种成员
  */
 void createRequest(int i,int j, int k);
 void *createThread(void *ptr);


}

-------------------------------
在 A.cpp中
void A::createRequest(int i,int j,int k)
{
  int ret;
  pthread_t tid;
  ret = pthread_create(&tid,NULL,createThread,(void*)&i);
}

void *createThread(void *ptr)
{
  this->id = ((int*)ptr); 
  printf("the id is %d \n", this->id);
}

程序报错:arguments: void*(A::)(void*) does not match void* (*)(void*)
是因为我在类中定义了线程的 start_routine函数么?

但是在createThread函数中,我其实是需要用到class A中的一些变量的,所以不好把createThread定义到class A之外。
谁能帮我想个解决方法啊?

我查了一些资料,解决方法大概有3种:
1.将线程函数作为全局函数, 从而避免了this指针作为隐含参数的作怪行为,但这样线程函数却无法访问类中的私有变量,此为一大缺憾。

2.使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。

3.把线程函数声明为友元函数,并在创建线程函数的时候把类的this指针传递过来,这样在线程函数中就可以使用类的成员了。
具体实现:pthead_create( &pthid, NULL, function, this );
  在function中, ( 类 * )p = (类 * )this;这样通过类似 p->m_num, 这样的调用,就可以调用C++类中的成员了。

问题就在于,如果把this指针传递过去的话,我怎么传递参数i给createThread 函数呢?

 

------解决方案--------------------
1. 将线程函数作为全局函数, 从而避免了this指针作为隐含参数的作怪行为,但这样线程函数却无法访问类中的私有变量,此为一大缺憾。
解决方案: 是把所有的私有变量变为全局变量,当然这样极大程度上破坏了类的封装性。
2. 把线程函数声明为友元函数,并在创建线程函数的时候把类的this指针传递过来,这样在线程函数中就可以使用类的成员了。
具体实现: pthead_create( &pthid, NULL, function, this );
在function中, ( 类 * )p = (类 * )this;这样通过类似 p->m_num, 这样的调用,就可以调用C++类中的成员了。
3. 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。

推荐第二种办法,定义start routione为全局函数或者友元函数,然后用struct把要的参数和类指针this一起传进去