如何取得实例的数据偏移 基类Base有虚函数,那么产生了vtable
那么派生类的实例如何去的数据区的起始位置
如
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void VFunc(){}
int k;
};
class Test : public Base
{
virtual void VFunc(){}
int t;
};
那么
Test test;
&test取得的地址为包含vtable的地址,数据出错,从哪个偏移开始才是数据区(基类数据和派生类数据)
问题补充:
或者说如何计算每个类的虚表大小,以及数据部分的排布
多重继承的情况下,数据分布是否带有先后顺序了
察看对应asm,发现简单继承的话,基类和派生类共用一个4字节的vtable区,基类数据和派生类数据在vtable后面连续存放
多重继承的话,会有其他操作,但是没找到准确说明这个问题的iso标准出处,所以问问
数据区排列:
Test Base
------- -----
|Test的vtable| |Base的vtable|
|Base的数据| |Base的数据|
|Test的数据|
可是在多重继承的时候好像是这样排布的,非常不解
Test Base Base2
------- ----- -----
|Test的vtable| |Base的vtable| |Base2的vtable|
|Base的数据| |Base的数据| |Base2的数据|
|Base2的vtable|
|Base2的数据|
|Test的数据|
然后自己动手实验
试验关于多重继承
实验环境:vc2005
class Base
{
public:
Base():k1(0)
{
}
virtual ~Base()
{
}
virtual void Func()
{
}
char k1;
};
class BaseB
{
public:
BaseB():t(0)
{
}
virtual ~BaseB()
{
}
char t;
};
class Test : public Base , public BaseB
{
public:
Test():d1(0)
{
}
~Test(){}
virtual void Func(){}
char d1;
};
Test test;
char* a = (char*)&test;
char* b = (char*)&(test.d1);
char* c = (char*)&(test.k1);
char* d = (char*)&(test.t);
a 0x0012ff50
b 0x0012ff60
c 0x0012ff54
d 0x0012ff5c
在看
实际上的顺序是Base,BaseB,Test
Base的数据与a的距离是4个字节,这4个字节应该是vtable
BaseB的数据与a的距离是12个字节,和Base的数据开始位置,相差8个字节,这里放了什么?不知道(如果数据以4字节对齐,那么就多了4个字节的BaseB的vtable,所以这两个积类的vtable就不是放在一起的)
Test的数据与a的距离时16个字节,按照上面的说法,不足4字节的,按4字节对齐,那么就对了
iso看不懂,也没找到具体说明这个的地方 |