WEB开发网
开发学院软件开发VC 直接调用类成员函数地址 阅读

直接调用类成员函数地址

 2010-07-25 20:45:42 来源:WEB开发网   
核心提示:三、调用成员函数地址通过上面两个方法,我们可以取到成员函数的地址,直接调用类成员函数地址(3),不过,如果不能通过地址来调用成员函数的话,这个是VC的默认类型),我们在调用之前加一句: mov ecx, this; 然后就可以调用成员函数指针,那也还是没有任何用处,当然

三、调用成员函数地址

通过上面两个方法,我们可以取到成员函数的地址。不过,如果不能通过地址来调用成员函数的话,那也还是没有任何用处。当然,这是可行的。不过在这之前,需要了解关于成员函数的一些知识。

我们知道,成员函数和普通函数最大的区别就是成员函数包含一个隐藏的参数this指针,用来表明成员函数当前作用在那一个对象实例上。根据调用约定(Calling Convention)的不同,成员函数实现this指针的方式也不同。如果使用__thiscall调用约定,那么this指针保存在寄存器ECX中,VC编译器缺省情况下就是这样的。如果是__stdcall或__cdecl调用约定,this指针将通过栈进行传递,且this指针是最后一个被压入栈的参数,相当于编译器在函数的参数列表中最左边增加了一个this参数。

这里还有件事不得不提,虽然vc将__thiscall类型作为成员函数的默认类型,但是vc6却没有定义__thiscall关键字!如果你使用__thiscall来定义一个函数,编译器报错:'__thiscall' keyword reserved for future use。

知道这些就好办了,我们只要根据不同的调用约定,准备好this指针,然后象普通函数指针一样的使用成员函数地址就可以了。

对__thiscall类型的成员函数(注意,这个是VC的默认类型),我们在调用之前加一句: mov ecx, this; 然后就可以调用成员函数指针。例如:

class tt
{
public:
  void foo(int x,char c,char *s)//没有指定类型,默认是__thiscall.
  {
    printf("
m_a=%d, %d,%c,%s
",m_a,x,c,s);
  }
  int m_a;
};
typedef void (__stdcall *FUNCTYPE)(int x,char c,char *s);//定义对应的非成员函数指针类型,注意指定__stdcall.
  tt abc;
  abc.m_a = 123;
  DWORD ptr;
  DWORD This = (DWORD)&abc;
  GetMemberFuncAddr_VC6(ptr,tt::foo); //取成员函数地址.
  FUNCTYPE fnFooPtr = (FUNCTYPE) ptr;//将函数地址转化为普通函数的指针.
  __asm //准备this指针.
  {
    mov ecx, This;
  }
  fnFooPtr(5,'a',"7xyz"); //象普通函数一样调用成员函数的地址.

对其它类型的成员函数,我们只要申明一个与原成员函数定义完全类似的普通函数指针,但在参数中最左边加一个void * 参数。代码如下:

class tt
{
public:
  void __stdcall foo(int x,char c,char *s)//成员函数指定了__stdcall调用约定.
  {
    printf("
m_a=%d, %d,%c,%s
",m_a,x,c,s);
  }
  int m_a;
};
typedef void (__stdcall *FUNCTYPE)(void *This,int x,char c,char *s);//注意多了一个void *参数.
  tt abc;
  abc.m_a = 123;
  DWORD ptr;
  GetMemberFuncAddr_VC6(ptr,tt::foo); //取成员函数地址.
  FUNCTYPE fnFooPtr = (FUNCTYPE) ptr;//将函数地址转化为普通函数的指针.
  fnFooPtr(&abc,5,'a',"7xyz"); //象普通函数一样调用成员函数的地址,注意第一个参数是this指针.

上一页  1 2 3 4 5 6  下一页

Tags:直接 调用 成员

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接