BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #77188同步于 2014/2/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

求教:多继承虚函数的内存分布问题

zr1010
2014/2/25镜像同步3 回复
验证代码如下:在VS2010里跑的 #include <iostream> using namespace std; class Base { public: virtual void f(){cout<<"Base::f()"<<endl;} virtual void g(){cout<<"Base::g()"<<endl;} virtual void h(){cout<<"Base::h()"<<endl;} }; class Base2 { public: virtual void f2(){cout<<"Base2::f2()"<<endl;} }; class Derived7:public Base,public Base2 { public: virtual void f(){cout<<"Derived7::f()"<<endl;} virtual void f1(){cout<<"Derived7::f1()"<<endl;} virtual void g1(){cout<<"Derived7::g1()"<<endl;} }; typedef void (*Fun)(); int main() { Derived7 *p7=new Derived7; int *Root=(int*)p7; int *VT=(int*)*(Root+0); while (*VT!=NULL) { (*(Fun*)(VT))(); VT++; } cout<<endl<<"seconde vptable:"<<endl; int *VT2=(int*)*(Root+1); while (*(VT2)!=NULL) { (*(Fun*)(VT2))(); (VT2)++; } delete p7; return 0; } 我理解在派生类虚函数表应该这样的: 从Base继承的第一张表 &Derived7::f() &Base::g() &Base::h() &Derived7::f1() &Derived7::g1() 从Base2继承的第二张表: &Base2::f2() 对不对? 运行完输出是对的,但是报错 SizeOfObject.exe 中的 0x00c086e0 处有未经处理的异常: 0xC0000005: Access violation 在标出的那一句那里,不懂为什么,查了报这个错可能的原因是指针没赋值就用造成的,但是貌似我没有呀。。。
订阅后,新回复会通过你的通知中心匿名送达。
3 条回复
gaoweiwei机器人#1 · 2014/2/26
依赖编译器的东西。从代码里看,你认为虚函数表的末尾还有一个指向NULL的slot,这个貌似没有吧(不确定,没在VS2010上测试过,不过应该不存在,因为没有存在的必要),另外,你的程序还有一些错误,比如调用类的非静态方法默认都有一个隐藏参数this,你定义的Func没有这个参数,并且调用的时候也没加参数,不过如果没有访问类的非静态数据成员的话这点可能不会引发错误,因此VS一般用寄存器来传递this指针,
zr1010机器人#2 · 2014/2/28
【 在 gaoweiwei 的大作中提到: 】 : 依赖编译器的东西。从代码里看,你认为虚函数表的末尾还有一个指向NULL的slot,这个貌似没有吧(不确定,没在VS2010上测试过,不过应该不存在,因为没有存在的必要),另外,你的程序还有一些错误,比如调用类的非静态方法默认都有一个隐藏参数this,你定义的Func没有这个参数,并且调用的时候也没加参数,不过如果没有访问类的非静态数据成员的话这点可能不会引发错误,因此VS一般用寄存器来传递this指针, 没有定义数据成员,就是想看虚函数表怎么存的 但是第一张虚函数表就都打出来了的,第二张怎么就不行了呢
tonyjansan机器人#3 · 2014/3/1
你确认是这样int* VT=(int*)*(ROOT + 0); 而不是这样int* VT=(int*)(ROOT + n); ? 【 在 zr1010 的大作中提到: 】 : 验证代码如下:在VS2010里跑的 : #include <iostream> : using namespace std; : ................... -------------------------分割线--------------------------- 改成这样试试,目测是虚表指针的结尾不是一个有效标识: while (*VT != NULL) ---> while (*VT > 0) while (*VT2 != NULL) ---> while (*VT2 > 0)