虚函数表 函数地址不一致问题, 困惑, 求高手解答

languagec 2009-11-28 02:22:31
// CPP.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#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 _tmain(int argc, _TCHAR* argv[])
{
Base * base=new Base();
BaseSec *basesec=new BaseSec();
Child *child=new Child;

typedef void (*Fun)(void);
Fun fP;

int *p= (int *) (*( (int *)base ) );
cout<<"Base:\t\t"<<p[0]<<"\t"; ((Fun)p[0])();
cout<<"Base:\t\t"<<p[1]<<"\t"; ((Fun)p[1])();

p= (int *)( *( (int*)basesec ) );
cout<<"BaseSec:\t"<<p[0]<<"\t"; ((Fun)p[0])();
cout<<"BaseSec:\t"<<p[1]<<"\t"; ((Fun)p[1])();

p= (int *)( *( (int*)child ) );
cout<<"Child:\t\t"<<p[0]<<"\t"; ((Fun)p[0])();
cout<<"Child:\t\t"<<p[1]<<"\t"; ((Fun)p[1])();
cout<<"Child:\t\t"<<p[1]<<"\t"; ((Fun)p[2])();

p= (int *)( *( (int*)child+1 ) );
cout<<"Child[1]:\t"<<p[0]<<"\t"; ((Fun)p[0])();
cout<<"Child[1]:\t"<<p[1]<<"\t"; ((Fun)p[1])();

return 0;
}



Child 类继承自Base和BaseSec类, 那么Child类对象中存在两个虚表指针。
经调用及查看虚表里函数地址,发现Child::Iam 函数地址在 Child类对象的两张虚表中函数地址并不一致。
执行结果如下:
Base: 4264091 Base::Iam
Base: 4264606 Base::FunBase
BaseSec: 4264631 BaseSec::Iam
BaseSec: 4264611 BaseSec::FunSec
Child: 4264241 Child::Iam
Child: 4264606 Base::FunBase
Child: 4264606 Child::Fun
Child[1]: 4264636 Child::Iam
Child[1]: 4264611 BaseSec::FunSec

可以看到:
Child: 4264241 Child::Iam
Child[1]: 4264636 Child::Iam

一个为4264241, 4264636, 但是调用时却调了同一个函数!

困惑, 难道同一个函数的函数地址会不一样么?

...全文
392 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
cswuyg 2010-09-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 languagec 的回复:]
你说的代理函数是存在虚表里面?
[/Quote]
没错,存在虚函数表里边的是“代理函数”地址。
languagec 2009-11-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sammylan 的回复:]
C/C++ code//楼主你的函数指针的定义是错误的typedefvoid (*Fun)(void);//应该这样定义typedefvoid (__thiscall*Fun)(void*pThis);//之所以同一个函数,他们的指针却不一样,是因为,函数里面需要对pThis进行指针调整.//拿以下几个函数的对应的C形式的指针为例virtualvoid Base::Iam();//类型为void ?-
[/Quote]

你说的代理函数是存在虚表里面?
macrojj 2009-11-28
  • 打赏
  • 举报
回复
Mark
SammyLan 2009-11-28
  • 打赏
  • 举报
回复

//楼主你的函数指针的定义是错误的
typedef void (*Fun)(void);
//应该这样定义
typedef void (__thiscall *Fun)(void*pThis);

//之所以同一个函数,他们的指针却不一样,是因为,函数里面需要对pThis进行指针调整.
//拿以下几个函数的对应的C形式的指针为例
virtual void Base::Iam(); //类型为void (__thiscall *IamBaseProxy)(Base*this);
virtual void BaseSec::Iam(); //类型为void (__thiscall *IamBaseSecProxy)(BaseSec*this);
virtual void Child::Iam(); //类型为void (__thiscall *IamChild)(Child*this);
//所以在Child对应的Base虚表里面,会存放一个代理函数,对应类型为Func1,
void __thiscall IamBaseSecProxy(BaseSec*this)
{
IamChild((Child*)this);
}

//在Child对应的BaseSec虚表里面,也会保存一个代理函数,对应类型为Func2
void __thiscall IamBaseProxy(Base*this)
{
IamChild((Child*)this);
}

mabo321 2009-11-28
  • 打赏
  • 举报
回复

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


class BaseSec //这儿 没有继承 Base 所以 Iam() 是不一样的
{
public:
virtual void Iam()
{
cout < <"BaseSec::Iam" < <endl;
}
virtual void FunSec()
{
cout < <"BaseSec::FunSec" < <endl;
}
};



对啊,地址就是不一样的
mengde007 2009-11-28
  • 打赏
  • 举报
回复
用VS调试下;
  • 打赏
  • 举报
回复
你无法获取成员函数的地址。

要真想研究这个,将整个类导出,然后看导出表。
  • 打赏
  • 举报
回复
[Quote=引用楼主 languagec 的回复:]
// CPP.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#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 _tmain(int argc, _TCHAR* argv[])
{
Base * base=new Base();
BaseSec *basesec=new BaseSec();
Child *child=new Child;

typedef void (*Fun)(void);
Fun fP;

int *p= (int *) (*( (int *)base ) );
cout < <"Base:\t\t" < <p[0] < <"\t"; ((Fun)p[0])();
cout < <"Base:\t\t" < <p[1] < <"\t"; ((Fun)p[1])();

p= (int *)( *( (int*)basesec ) );
cout < <"BaseSec:\t" < <p[0] < <"\t"; ((Fun)p[0])();
cout < <"BaseSec:\t" < <p[1] < <"\t"; ((Fun)p[1])();

p= (int *)( *( (int*)child ) );
cout < <"Child:\t\t" < <p[0] < <"\t"; ((Fun)p[0])();
cout < <"Child:\t\t" < <p[1] < <"\t"; ((Fun)p[1])();
cout < <"Child:\t\t" < <p[1] < <"\t"; ((Fun)p[2])();

p= (int *)( *( (int*)child+1 ) );
cout < <"Child[1]:\t" < <p[0] < <"\t"; ((Fun)p[0])();
cout < <"Child[1]:\t" < <p[1] < <"\t"; ((Fun)p[1])();

return 0;
}


Child 类继承自Base和BaseSec类, 那么Child类对象中存在两个虚表指针。
经调用及查看虚表里函数地址,发现Child::Iam 函数地址在 Child类对象的两张虚表中函数地址并不一致。
执行结果如下:
Base:          4264091 Base::Iam
Base:          4264606 Base::FunBase
BaseSec:        4264631 BaseSec::Iam
BaseSec:        4264611 BaseSec::FunSec
Child:          4264241 Child::Iam
Child:          4264606 Base::FunBase
Child:          4264606 Child::Fun
Child[1]:      4264636 Child::Iam
Child[1]:      4264611 BaseSec::FunSec

可以看到:
Child:          4264241 Child::Iam
Child[1]:      4264636 Child::Iam

一个为4264241, 4264636, 但是调用时却调了同一个函数!

困惑, 难道同一个函数的函数地址会不一样么?


[/Quote]
会。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧