static void* worker(void *arg)
1、worker函数的作用只是用来调用run()函数,那么为什么不直接用run()函数,而要借用worker函数多此一举呢?
2、为什么worker()函数一定要是静态成员函数呢?
这就是C++和C不一样的地方了
首先,我们来思考一下,这个run()函数的功能是什么?
正如上图的注释写到的那样:“ /*工作线程执行的函数,不断从工作队列中取出任务并执行*/ ” !
既然如此,run()如果按照C语言里面的写法,可以直接写成线程的执行函数了,如下:
/*pthread_create()定义如下*/ /*int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);*/ /*线程执行函数*/ void * run(void *arg){ .... return NULL; } int main(){ /*创建子线程*/ pthread_create(&fd,NULL,run,NULL); return 0; }
如果C++和C没有区别的话,写到这里也就万事大吉了,但是,事情没有这么简单。
回忆一下,我们知道,C++类内的成员变量和成员函数是分别存放的,类内成员函数在内存中只有一份,类的所有实例都是访问这一份内存来调用同一成员函数的,那么问题来了,这个成员函数是怎么知道是哪份实例在调用自己的呢?是张三调用自己还是李四调用自己呢?
一门编程语言肯定要能够自圆其说,而
this
指针可以用来解决这个问题!!我们知道,C++类内非静态成员函数的第一个参数其实是隐藏的this
指针:T* const register this
,这个指针指向调用该非静态成员函数的对象实例,这样的话,非静态成员函数就能够知道是哪个实例在调用自己。回到上面线程执行函数这个话题,在游双的书中,线程执行函数
run()
是在类内的,所以它的第一个默认参数是this
指针,而pthread_create()
第三个参数只接受唯一的一个void*
参数,但是加上this
指针,一共两个参数,所以线程执行函数会出错。那么我们就要想办法解决这个问题了,既然在这个地方
this
指针不被欢迎,那我们就丢掉它,正巧,静态成员函数没有this
指针,因为静态成员函数独立于任何实例对象,也就是所有实例对象在调用它的时候,它并不需要区分是谁在调用自己。貌似到这里柳暗花明了,我们是不是只需要把
run()
定义为静态成员函数就行了呢?很可惜,答案是否定的。
正因为静态成员函数没有this指针,不知道应该访问哪个对象中的数据,所以在程序中不可以用静态成员函数直接访问类中的动态成员(包括非静态成员函数和非静态成员变量),而要达到此目的,只能通过两种方式实现:
- 通过类的静态对象来调用。比如单例模式中,静态函数可以通过类的全局唯一实例了来访问动态成员函数。
- 将类的对象作为参数传递给该静态函数,然后在静态函数中引用这个对象,并调用其动态方法。
书中使用的便是第二中方法:创建一个静态成员函数
worker()
,然后在worker()
里面调用run()
,这下就解释了开头的两个问题至此,所有的疑惑都已烟消云散!