Author:Jeff 2005-12-2
关键字:C++ 虚函数 访问机制
环境:Window XP Professional + SP2, VC6.0
上一篇文章中,在统计虚函数的个数时,依靠的就是其地址。虚函数的地址都有了,如果不调用一下,太对不起人了。*_*!。 但令人沮丧的是,C++中对类的成员变量及成员函数有严格的访问权限,你光明正大地调用C++的private虚函数,在编译期就通不过,即使你知道其地址又有什么用~~~
看看下面这个简单的代码:
#include <stdio.h>
void outp(void) {
printf("function Outp()/n");
}
int main(void)
{
void (*k)(void) = outp;
int *s = (int *)outp;
k(); // correct
// s(); incorrect
return 0;
}
对于s来说,其实它已经取得了函数Outp()的入口地址,但是就是不能像这样调用:s()。因为s所拥有的信息不允许这样匹配,在语法分析阶段就夭折了。要躲过C++编译器语法分析和语义分析阶段的盘查,只得用比较原始的方法,汇编调用:
_asm {
call [s]
};
呵呵,效果等同于k()。
对class的private虚函数,也可以用汇编代码来调用,巧妙地绕过class的访问权限(其实是绕过C++编译器语法分析和语义分析阶段)。
借助上一篇章的代码,在main()函数加入下面的代码:
int *p = (int *)&c1;
int *q, *r;
q = (int *)*((int *)(*p) + 1);
r = (int *)*((int *)(*p) + 2);
_asm {
call [q] ; // complement second virtual function
};
_asm{
push 23
call [r] ; // complement third virtual function
};
程序忠实地执行了C001::Display()和C001::Outp(),再现了private虚函数运行后的结果。
遗憾的是,对于带参数的虚函数,在使用汇编代码调用时,需要知道参数的个数、大小和类型,和普通方式调用差不多。在没有源代码的情况下,很难调用成功。