虚函数表地址问题

vcgaoshou 2013-10-20 04:35:47
类继承如下
#include<iostream>
using namespace std;
class Base1{
public:
virtual void f(){cout<<"Base1::f()"<<endl;}
virtual void g(){cout<<"Base1::g()"<<endl;}
virtual void h(){cout<<"Base1::h()"<<endl;}
};
class Base2{
public:
virtual void f(){cout<<"Base2::f()"<<endl;}
virtual void g(){cout<<"Base2::g()"<<endl;}
virtual void h(){cout<<"Base2::h()"<<endl;}
};
class Base3{
public:
virtual void f(){cout<<"Base3::f()"<<endl;}
virtual void g(){cout<<"Base3::g()"<<endl;}
virtual void h(){cout<<"Base3::h()"<<endl;}
};
class Derive:public Base1,public Base2,public Base3{
public:
virtual void f(){cout<<"Derive::f()"<<endl;}
virtual void g1(){cout<<"Derive::g1()"<<endl;}
};
typedef void (*Fun)(void);
int main(){
Fun pFun=NULL;
Derive d;
int ** pVtab=(int**)&d;
// pFun=(Fun)*((int*)*(int*)&d);
// cout<<((int*)*(int*)&d)<<endl;
// cout<<((int*)*((int*)&d+1))<<endl;
pFun=(Fun)pVtab[0][1];
pFun();
pFun=(Fun)pVtab[1][1];
pFun();
return 0;
}
主函数中
int ** pVtab=(int**)&d;
pFun=(Fun)pVtab[0][1];
pFun();
pFun=(Fun)pVtab[1][1];
pFun();
就分别调用了Base1::g(),Base2::g()
不明白int ** pVtab=(int**)&d;语句的含义,(int**)&d将d对象地址转换成什么类型的指针,
pVtab[0][1],pVtab[1][1]是数组形式,为什么可以这样访问虚函数
难道系统会把3个基类的虚函数表组织成1个2维数组,在内存中是连续的?

...全文
204 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
水平不流 2013-10-27
  • 打赏
  • 举报
回复
引用 9 楼 wangdahu888 的回复:
[quote=引用 7 楼 ak47_wz 的回复:] 好像今天看到过这种问题。 那个谁谁谁,说,C++保留指针是最大的败笔。
不用指针,哪来效率?[/quote] 这句话我已经忘了是谁说的.貌似是JAVA之父还是哪个业界C语言大神说的.英文名字...情何以堪.
  • 打赏
  • 举报
回复
引用 7 楼 ak47_wz 的回复:
好像今天看到过这种问题。 那个谁谁谁,说,C++保留指针是最大的败笔。
不用指针,哪来效率?
lm_whales 2013-10-27
  • 打赏
  • 举报
回复
C++的成员指针,似乎可以调用虚函数。因为可以传递 this 指针。
水平不流 2013-10-26
  • 打赏
  • 举报
回复
好像今天看到过这种问题。 那个谁谁谁,说,C++保留指针是最大的败笔。
lm_whales 2013-10-26
  • 打赏
  • 举报
回复
虚函数表中的虚函数指针的类型,是无法用C式样的的函数指针严格定义的。 因为 1)每个虚函数的类型,都不一定相同。 2)C++的this 指针这个隐藏参数,C式样的的函数指针,无法定义出带有这种参数的函数指针。 因为,这种调用方式的这个参数的传递方式,不同与各种调用约定,是一种独特传递方式。 其中,VC,X86 ,32Bits 使用 ecx寄存器,传递这个参数。 基本上,直接用C函数指针模拟,虚函数的调用方式,都是错误的。 所以,不使用汇编,简单使用C的方式,企图实现调用虚函数,是达不到目的,通常会出错的。
碼上道 2013-10-26
  • 打赏
  • 举报
回复
引用 4 楼 vcgaoshou 的回复:
我不是关注对应类的内存布局,而是不理解 int ** pVtab=(int**)&d; 中(int**)&d 和** pVtab的含。即 把d转换成了什么类型的地址,pVtab经**后,成了什么类型的指针
是因为d对象在内存在的第一个int也是一个指针,其实就是vfptr指针,这个指针指向vtable。所以才用int **转一下&d.
vcgaoshou 2013-10-26
  • 打赏
  • 举报
回复
我不是关注对应类的内存布局,而是不理解 int ** pVtab=(int**)&d; 中(int**)&d 和** pVtab的含。即 把d转换成了什么类型的地址,pVtab经**后,成了什么类型的指针
  • 打赏
  • 举报
回复
引用 2 楼 worldy 的回复:
[quote=引用 1 楼 wangdahu888 的回复:] vc环境下,用命令行执行: cl 你的程序文件.cpp -d1 reportSingleClassLayout[classname] // reportSingleClassLayout和[classname]之间没空格。 就直接打印出对应类的内存布局了,一览无余!!
请教: vc环境下,用命令行执行: 命令行是在哪? [/quote] 在开始->所有程序->你的vs的安装目录->visual studio tools 里面有个 visual studio 命令提示
worldy 2013-10-20
  • 打赏
  • 举报
回复
引用 1 楼 wangdahu888 的回复:
vc环境下,用命令行执行: cl 你的程序文件.cpp -d1 reportSingleClassLayout[classname] // reportSingleClassLayout和[classname]之间没空格。 就直接打印出对应类的内存布局了,一览无余!!
请教: vc环境下,用命令行执行: 命令行是在哪?
  • 打赏
  • 举报
回复
vc环境下,用命令行执行: cl 你的程序文件.cpp -d1 reportSingleClassLayout[classname] // reportSingleClassLayout和[classname]之间没空格。 就直接打印出对应类的内存布局了,一览无余!!

64,654

社区成员

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

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