您的位置:首页 > 其它

如何通过函数名获取虚函数的地址?

2017-03-25 00:00 411 查看
测试环境:WIN8+VS2012

#include <iostream>
#include <cstdio>
using namespace std;

class Cbase{
public:
Cbase() : x(10){}
virtual void f(){cout << "Cbase::f" << endl;}
virtual void g(){cout << "Cbase::g" << endl;}
virtual void h(){cout << "Cbase::h" << endl;}
private:
int x;
};
typedef void(*FUN)();
typedef void(Cbase::*PFUN)();
int main(void)
{
Cbase a;
printf("f = 0%X\n", &Cbase::f);
printf("g = 0%X\n", &Cbase::g);
printf("h = 0%X\n", &Cbase::h);

PFUN c1 = &Cbase::f;
PFUN c2 = &Cbase::g;
PFUN c3 = &Cbase::h;
(a.*c1)();
(a.*c2)();
(a.*c3)();

return 0;
}
输出:



既然能够正常输出,我们有理由相信&Cbase::f,&Cbase::g,&Cbase::h,是虚函数表里的地址,事实是这样吗?

有些书上说是获取到虚函数在虚函数表中的索引。但是实际上VS编译器并不是这么做的,获取到的将会是一个用于虚函数调用的地址,这个地址上的指令会先获取虚函数表,然后再通过虚函数表获取虚函数地址相关的项。而GCC的做法又跟VS不同,通过&获取得的值都是1。总而言之,通过取地址&符号获得的不是函数地址,但是可以通过获得的值成功调用该函数。

但在vs中,成员函数指针不是指向函数的真实地址,而是先指向一个位置,该位置会调用Cbase::`vcall'{0}':之后才跳转到真正地址。不同的函数,Cbase::`vcall'{0}':中的数字不同。



本质上还是编译时确定好每个函数的位置,通过此位置来查询虚函数表。

而在VS中,*(int*)*(int*)(&b)也依旧取不到虚函数表地址



可见经过了一次jmp

为什么会jmp,其实和普通函数一样

http://blog.csdn.net/x_iya/article/details/13161937

====================

#include <map>
#include <iostream>
using namespace std;

class Base
{
public:
virtual void Iam()
{
cout<<"Base::Iam"<<endl;
}
virtual void FunBase()
{
cout<<"Base::FunBase"<<endl;
}
};

class BaseSec
{
public:
virtual void Iam()
{
cout<<"BaseSec::Iam"<<endl;
}
virtual void FunSec()
{
cout<<"BaseSec::FunSec"<<endl;
}
};

class Child: public Base, public BaseSec
{
public:
virtual void Iam()
{
cout<<"Child::Iam"<<endl;
}

virtual void Fun()
{
cout<<"Child::Fun"<<endl;
}
};

int main(void)
{
typedef void(*Fun)(void);
Fun fun;
Child child;
typedef void (*Fun)(void);
int **p = (int**)&child;
cout << p[0][0] << endl;
fun = (Fun)p[0][0];
fun();

cout << p[0][1] << endl;
fun = (Fun)p[0][1];
fun();

cout << p[0][2] << endl;
fun = (Fun)p[0][2];
fun();

p = (int**)&child+1;

cout << p[0][0] << endl;
fun = (Fun)p[0][0];
fun();

cout << p[0][1] << endl;
fun = (Fun)p[0][1];
fun();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: