在使用Windows、Linux创建线程时,当要把某个函数作为线程的启动函数时,此函数必须为全局函数或者静态函数。而如果这个启动函数刚好又在类里面,那只能将此函数定义为类的静态函数。但是既然在类里面,应该是调用了类里的其他方法的,不然完全可以写成全局函数。如果该类中的静态函数又要调用类的其他非静态方法,那就涉及到类的静态成员对非静态成员的调用,实现这种调用有几种方案,可以记录一下。
1、将类对象的指针作为参数传进static函数中,在函数中用对象指针去调用对应函数。但是这样也只能调用public属性的类函数。
2、直接定义一个静态对象,那整个对象的内容都是在静态区里面。
static void Run(void* lpParameter);
static DWORD WINAPI Run2(LPVOID lpParameter);
//这个地方要自己起线程了,起了线程之后还需要join或者detach
//return CLoopTask::Create(iPriority, "tNetScrt", 32*1024, 0);
#ifdef WIN32
HANDLE tNetScrt = CreateThread(NULL, 32 * 1024, CZH5NNetSecurity::Run2, (void*)this, 0, 0);
#endif
#ifdef __linux__
pthread_t tNetScrt;
pthread_create(&tNetScrt, NULL, Run(), (void*)this); //Run是静态函数
pthread_setname_np(tNetScrt, "tNetScrt");
#endif
最开始的时候未设置成静态函数,编译的时候直接报不兼容。原因如下:
因为类的非静态函数的形参其实比表面看到的会多一个this,只是我们看不到而已,实际是有的。而线程函数的形参形式又已经定好了,不可能还有个什么类的指针,所以会报不兼容问题。
类的非静态成员函数的函数形参中其实有一个未显示出来的this指针,只是我们在表面上看不到而已,底层是有的。这个指针用于区分是哪个对象调用的,因为类的存储机制是所有对象共用一套代码,只是拥有各自的变量而已。而static函数作为线程启动入口参数,而又要调用类的其他方法,就只能又在传一个对象的指针进去实现调用(基本上可以直接传this指针),因为static函数没有this指针,即静态函数只能调用静态成员,而非静态函数则静态非静态成员都可以调用,这其实就关联到程序在内存中的存储了,静态变量存在全局\静态区,非静态是存在栈上的。总结,采用Windows和Linux的系统函数起线程时要静态函数因为静态函数才没有this指针,才和起线程函数中的形参对应;而静态函数有调用到类的非静态方法时又要把this指针作为参数传进去。