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

直接调用类成员函数地址

 2010-07-25 20:45:42 来源:WEB开发网   
核心提示:四、进一步的讨论到目前为止,已经讨论了如何取成员函数的地址,直接调用类成员函数地址(5),然后如何使用这个地址,但是还有些重要的情况没有讨论,因此它会暗中作替换,编译器(VC6)产生的代码如下:GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1); //源代码.//VC6编译器产生的汇编

四、进一步的讨论

到目前为止,已经讨论了如何取成员函数的地址,然后如何使用这个地址。但是还有些重要的情况没有讨论,我们知道成员函数可分为三种:普通成员函数,静态,虚拟。另外更重要的是,在继承甚至多继承下情况如何。

首先看看最简单的单继承,非虚拟函数的情况。

class tt1
{
public:
  void foo1(){ printf("
hi, i am in tt1::foo1
"); }
};
class tt2 : public tt1
{
public:
  void foo2(){ printf("
hi, i am in tt2::foo2
"); }
};

注意,tt2中没有定义函数foo1,它的foo1函数是从tt1中继承过来的。这种情况下,我们直接取tt2::foo1的地址行会发生什么?

DWORD tt2_foo1;
tt1 x;
GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1);
CallMemberFunc(0,tt2_foo1,&x,0); // tt2::foo1 = tt1::foo1

运行结果表明,一切正常!当我们写下tt2::foo1的时候,编译器知道那实际上是tt1::foo1,因此它会暗中作替换。编译器(VC6)产生的代码如下:

GetMemberFuncAddr_VC6(tt2_foo1,&tt2::foo1); //源代码.
//VC6编译器产生的汇编代码:
push offset @ILT+235(tt1::foo1) (004010f0) //直接用tt1::foo1 替换 tt2::foo1.
...

再看看稍微复杂些的情况,继承情况下的虚拟函数。

class tt1
{
public:
  void foo1(){ printf("
hi, i am in tt1::foo1
"); }
  virtual void foo3(){ printf("
hi, i am in tt1::foo3
"); }
};
class tt2 : public tt1
{
public:
  void foo2(){ printf("
hi, i am in tt2::foo2
"); }
  virtual void foo3(){ printf("
hi, i am in tt2::foo3
"); }
};

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

Tags:直接 调用 成员

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