yang79tao()
的说法是错误的.线程函数,是需要一个函数指针,对这个函数指针的唯一要求是
它的类型必须符合要求.
因为这个指针要用来做线程启动函数(beginthread等)的参数,类型不符合肯定不行.
为了符合这个类型,函数我们按照一般格式定义就可以了.
成员函数的地址也是在编译的时候就确定了的.
只有成员变量,因为它属于对象,而对象是运行的时候创建的,所以成员变量的地址是运行时候才确定的.
的说法是错误的.线程函数,是需要一个函数指针,对这个函数指针的唯一要求是
它的类型必须符合要求.
因为这个指针要用来做线程启动函数(beginthread等)的参数,类型不符合肯定不行.
为了符合这个类型,函数我们按照一般格式定义就可以了.
成员函数的地址也是在编译的时候就确定了的.
只有成员变量,因为它属于对象,而对象是运行的时候创建的,所以成员变量的地址是运行时候才确定的.
Cxxx::func1(LPARAM lParam);
实际调用时会被展开成 func1(pClass->this, lParam); 用汇编表示如下:
push lParam
push pClass->this
call func1而一般的函数或类的静态成员函数调用时为
push lParam
call func1
那么a1与a2中的同一个成员函数的地址,怎么可能相同呢?
如果是一般的成员函数,则等价于 LRESULT proc1(Cxxx *pThis, LPVOID pv); 函数真正的参数个数是二个。
而静态成员函数则仍为LRESULT proc1(LPVOID pv); 与全局函数没有区别,相当于只是多了个命名空间(namespace)
笑死,,,,,,,,,
既然这样,成员函数也可以作为线程函数,只要把成员函数的地址强行改成LRESULT proc1(LPVOID pv); 的样子不就行了?
c++编译器在编译时会自动修改成LRESULT proc1(Cxxx *, LPVOID)的形式。
如果我把成员函数的地址当成一个32位的整数来看待(实际上就是个整数),那么再将这个整数转换成LRESULT proc1(LPVOID pv)样子的指针,也不行吗?
而成员函数隐含this指针后,长度由编译器决定的。
直接转换的结果是信息丢失,不能保证调用正确。
如果坚持使用,那么就是一个未定义的行为。下面是网上搜来的。
成员函数指针——为什么那么复杂?
类的成员函数和标准的C函数有一些不同。与被显式声明的参数相似,类的成员函数有一个隐藏的参数this,它指向一个类的实例。根据不同的编译器,this或者被看作内部的一个正常的参数,或者会被特别对待(比如,在VC++中,this一般通过ECX寄存器来传递,而普通的成员函数的参数被直接压在堆栈中)。this作为参数和其他普通的参数有着本质的不同,即使一个成员函数受一个普通函数的支配,在标准C++中也没有理由使这个成员函数和其他的普通函数(ordinary function)的行为相同,因为没有thiscall关键字来保证它使用像普通参数一样正常的调用规则。成员函数是一回事,普通函数是另外一回事(Member functions are from Mars, ordinary functions are from Venus)。
你可能会猜测,一个成员函数指针和一个普通函数指针一样,只是一个代码指针。然而这种猜测也许是错误的。在大多数编译器中,一个成员函数指针要比一个普通的函数指针要大许多。更奇怪的是,在Visual C++中,一个成员函数指针可以是4、8、12甚至16个字节长,这取决于它所相关的类的性质,同时也取决于编译器使用了怎样的编译设置!成员函数指针比你想象中的要复杂得多,但也不总是这样。
http://study.pay500.com/2/s29208.htm,这里这篇文章。
其实 chehw(chehw) 说的很对,我没有太多补充。系统启动线程时,根据约定,也即线程函数指针的定我,总是传入一个参数给这个函数。如果你这样强行转换,你给定的函数指针指向的函数,实际是有两个参数,这样,压入两个参数,弹出一个参数,会发生什么?
其实,创建线程的时候,仅需要一个 函数指针, 这个指针指向任何地址空间都可以,在编译期间都是可以通过的。