返回信息流验证代码如下:在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
在标出的那一句那里,不懂为什么,查了报这个错可能的原因是指针没赋值就用造成的,但是貌似我没有呀。。。
这是一条镜像帖。来源:北邮人论坛 / cpp / #77188同步于 2014/2/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
求教:多继承虚函数的内存分布问题
zr1010
2014/2/25镜像同步3 回复
订阅后,新回复会通过你的通知中心匿名送达。
3 条回复
依赖编译器的东西。从代码里看,你认为虚函数表的末尾还有一个指向NULL的slot,这个貌似没有吧(不确定,没在VS2010上测试过,不过应该不存在,因为没有存在的必要),另外,你的程序还有一些错误,比如调用类的非静态方法默认都有一个隐藏参数this,你定义的Func没有这个参数,并且调用的时候也没加参数,不过如果没有访问类的非静态数据成员的话这点可能不会引发错误,因此VS一般用寄存器来传递this指针,
【 在 gaoweiwei 的大作中提到: 】
: 依赖编译器的东西。从代码里看,你认为虚函数表的末尾还有一个指向NULL的slot,这个貌似没有吧(不确定,没在VS2010上测试过,不过应该不存在,因为没有存在的必要),另外,你的程序还有一些错误,比如调用类的非静态方法默认都有一个隐藏参数this,你定义的Func没有这个参数,并且调用的时候也没加参数,不过如果没有访问类的非静态数据成员的话这点可能不会引发错误,因此VS一般用寄存器来传递this指针,
没有定义数据成员,就是想看虚函数表怎么存的
但是第一张虚函数表就都打出来了的,第二张怎么就不行了呢
你确认是这样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)