成员函数指针【转贴】
来源:互联网 发布:淘宝店铺裤子类标志 编辑:程序博客网 时间:2024/04/30 02:07
#include "stdio.h"
class A
{
public:
virtual void t(){printf("base/n");};
virtual void t2(){};
int rt()
{
printf("non virtual func/n");
return 1;
};
};
class B:public A
{
public:
virtual void t(){ printf("derive/n");};
virtual void t2(){};
};
void justfun()
{
int a;
a=0;
};
int main()
{
A *p;
B O;
p=&O;
int(*cast)();
void(*nof)();
void(A::*pmf)();
int(A::*rpmf)();
nof=&justfun;
rpmf=&A::rt;
pmf=&A::t2;
// cast=(int * ())(rpmf);
__asm
{
push eax
mov eax,rpmf
mov cast,eax
pop eax
}
printf("%x %x %x/n",nof,pmf,rpmf);
(*cast)();
(*nof)();
(p->*rpmf)();
(O.*pmf)();
(p->*pmf)();
pmf=&A::t;
(p->*pmf)();
p->t2();
return 0;
}
今天早上看到一个朋友的留言,关于通过成员函数指针调用成员函数的问题。
成员函数指针调用跟普通函数指针调用不同。
因为成员函数有虚函数和非虚函数的差别,调用的时候,跟普通非成员函数调用有不同。
对于非成员函数,取函数名的地址,得到的就是该函数内存中的起始地址,然后直接调用就可以。在汇编层面上,就是直接call addr.
对于非虚成员函数,取得的地址其实也就是完整的函数地址。可以直接调用。但是因为类型的原因,不能把成员函数的地址直接给一个普通的函数指针。成员函数指针的类型是classname::ptr的形式,而且是thiscall,thiscall是c++保 留关键字,所以无法直接给一个普通的函数指针,用强制转换也不行。因为c++不允许对函数指针类型做强制转换,所以我在上面的代码中用嵌入汇编,完成强制转换,通过调用,发现上面的理解是正确的。
对于虚成员函数就比较麻烦。如果不用指针调用,编译器就直接把object的地址放到ecx中,其实也就是vtable的地址,然后在这个vtable上就可以找到正确的函数。如果通过指针调用,编译器无法保证这个指针以后会不会发生变化,也就是说这个指 针变量,以后可能会指向这个class的其他成员函数,所以编译器一旦检测到这种&classname::funcname的时候,就会生成一个vcall,然后把vcall的地址作为&classname::funcname的结果返回。vcall其实指向的是一组代码,大概如下形式:
mov eax,[ecx]
call [eax+n]
其中n是根据不同funcname在vtable中不同偏移决定的。前面说过,如果不通过指针调用,编译器可以根据函数名字找到偏移,但是通过指针,编译器就找不到名字了,找到的是一个地址,所以必须在地址上强制生成这个n.所以代码的作用就是在vtab le,也就是[ecx]中,找到正确的函数。
上面的结论是我调试出来的,大家可以在中间放断点,通过alt+8查看汇编代码,得到结论。
同时c++标准没有规定编译器实现细节,上面的东西只对vc6 debug模式下有说明作用。
- 成员函数指针【转贴】
- 函数指针 成员函数指针
- 类成员函数指针
- 成员函数指针数组
- 成员函数 指针
- 类成员函数指针
- 类成员函数指针
- 成员函数的指针
- 成员函数指针数组
- 成员函数指针
- 类成员函数指针
- 类成员函数指针
- 理解成员函数指针
- c++ 成员函数指针
- 类成员函数指针
- c++ 成员函数指针
- 笔记:成员函数指针
- “类” 成员函数 指针
- const修饰指针和引用的用法【转贴】
- 指针很值得注意的问题【转贴】
- ASP.net DropDownList 无刷新联动菜单
- Windows消息大全【转贴】
- ASP.NET程序中常用的三十三种代码
- 成员函数指针【转贴】
- auto、static、register、const、volatile 、extern 总结【转贴】
- __cdecl,__fastcall, __stdcall 什么区别?【转贴】
- 如何用.NET创建Windows服务 详解
- datagrid数据导出到excel文件给客户端下载的几种方法
- 简单人生
- 共享内存实现进程间大数据的交换
- C#寻找素数的算法
- 转:最近看了一篇文章用PHP实现手机对jar,jad文件的下载 作者:陈泽|SurfChen