C++和函数指针和线程函数

虽然标题是这么写的不过还是倒过来先从线程说起吧,Windows via C/C++里提到的线程函数实现这里就不说了,只说创建需要给的一个函数指针。
uintptr_t _beginthreadex( 

   void *security,    // security properties, pass NULL for most times

   unsigned stack_size,    // pass 0 to use a default thread stack size

   unsigned ( *start_address )( void * ),    // pointer to a function where thread starts

   void *arglist,    // the function may needs parameters

   unsigned initflag,    // pass NULL to start the thread right after the _beginthreadex function

   unsigned *thrdaddr     // pointer to an unsigned integer for holding the thread ID

);

Windows下创建线程使用CreateThread的API,Windows的C Runtime里提供了如上的函数。由于CRT里有一些全局变量如errno,所以如果在线程中使用了C函数,那可能会发生多线程访问该全局变量的问题(当然C标准库里大多数函数都是线程安全的),所以该书作者表示尽可能地别用CreateThread,都用_beginthreadex(在<process.h>中),反正它们的参数完全一样,就是类型不同需要强制转换。

扯远了,问题1:需要关注的就是那个start_address变量,是一个指向unsigned (*)(void*)函数的指针。对一个类A而言,它的成员函数指针则是unsigned (A::*)(void*)的。

class A {

    unsigned Foo(void*) { return 0; }

};

 

typedef unsigned (*FUNC1)(void*);

typedef unsigned (A::*FUNC2)(void*);

后来多次尝试+Google后发现无论怎样都不可以把后一种函数指针赋给前一个类型的参数,除非你另写一个C函数包一下(如下),就算我自己做了成员函数访问成员变量的互斥操作都不行!
A obj;

 

unsigned FUNC_WRAPPER(void* p) {

    obj.Foo(p);

}

 

也就是说多线程必须使用全局函数了。

问题2:成员函数的指针的用法。

在知道类成员函数指针不能赋值给全局函数指针之后,想合法地尝试一下:

class A {

public:

    unsigned Foo(void*) { return 0; }

    

    void Test(unsigned (A::*pFoo)(void*), void* p) {

        pFoo(p);    // Compiler Error

    }

};

 

int main() {

    A a;

    a.Test(A::Foo);    // Error

    a.Test(&A::Foo);    // OK

 

    return 0;

}

 

上述main函数中的错误行,要获得一个成员函数指针,需要用&A::Foo才行,不可以用A::Foo,VS也会提示你更改为正确的方式。

而A::Test()函数中的错误就有点麻烦了,需要更正为:

class A {
public:
    unsigned Foo(void*) { return 0; }

    void Test(unsigned (A::*pFoo)(void*), void* p) {
        (this->* pFoo)(p);    // inside the class itself, use "this" pointer
    }
};

void GlobalTest(unsigned (A::*pFoo)(void*), void* p) {
    A a;
    (a.* pFoo)(p);    // in a global function, use class instance
}

另外,由于这样写起来很麻烦,也可以用typedef:
class A {

public:

    typedef unsigned (A::*FUNC_PTR)(void*);

 

    unsigned Foo(void*) { return 0; }

 

    void Test(FUNC_PTR pFoo, void* p) {

        (this->* pFoo)(p);    // inside the class itself, use "this" pointer

    }

};

 

void GlobalTest(A::FUNC_PTR pFoo, void* p) {

    A a;

    (a.* pFoo)(p);    // in a global function, use class instance

}

关于这个问题2, 在MSDN里有类似的三个更具代表性的错误和解决方式。也可以参考一下 高人维护的C++ FAQ的 第33点。

跪求大大解释一下上面成员函数指针的运行机理orz


你可能感兴趣的:(thread,C++,windows,function,Security,Class)