#include <iostream>
using namespace std;
class BB
{
public:
int bb_;
};
class B1:virtual public BB
{
public:
int b_;
};
class B2:virtual public BB
{
public:
int b2_;
};
class DD:public B1,public B2
{
public:
int dd_;
};
int main(void)
{
cout<<sizeof(BB)<<endl;//4
cout<<sizeof(B1)<<endl;//12
cout<<sizeof(DD)<<endl;//24
return 0;
}
根据以前的理论:BB,4个字节,B1,8个字节,DD 16个字节。。
推导B1的内存模型:
地址打印输出:
B1 b1;
cout<<&b1<<endl;
cout<<&b1.bb_<<endl;
cout<<&b1.b_<<endl;
打印结果:
0024F8D4
0024F8DC
0024F8D8
#include <iostream>
using namespace std;
class BB
{
public:
int bb_;
};
class B1:virtual public BB
{
public:
int b_;
};
class B2:virtual public BB
{
public:
int b2_;
};
class DD:public B1,public B2
{
public:
int dd_;
};
int main(void)
{
cout<<sizeof(BB)<<endl;//4
cout<<sizeof(B1)<<endl;//12
cout<<sizeof(DD)<<endl;//24
B1 b1;
long** p;//定义指针的指针
cout<<&b1<<endl;
cout<<&b1.bb_<<endl;
cout<<&b1.b_<<endl;
p=(long**)&b1;//指向b1 对象,看图:所以这里就把b1 的地址转换成指针的指针
//p[0];// p[0] 就是图 vbptr,指向vbtl
cout<<p[0][0]<<endl;//0
cout<<p[0][1]<<endl;//8
//打印结果与图相同 符合预期
return 0;
}
cout<<&dd<<endl;
cout<<&dd.bb_<<endl;
cout<<&dd.b1_<<endl;
cout<<&dd.b2_<<endl;
cout<<&dd.dd_<<endl;
dd对象的内存模型图(不忍直视)
#include <iostream>
using namespace std;
class BB
{
public:
int bb_;
};
class B1:virtual public BB
{
public:
int b1_;
};
class B2:virtual public BB
{
public:
int b2_;
};
class DD:public B1,public B2
{
public:
int dd_;
};
int main(void)
{
cout<<sizeof(BB)<<endl;//4
cout<<sizeof(B1)<<endl;//12
cout<<sizeof(DD)<<endl;//24
B1 b1;
long** p;//定义指针的指针
cout<<&b1<<endl;
cout<<&b1.bb_<<endl;
cout<<&b1.b1_<<endl;
p=(long**)&b1;//指向b1 对象,看图:所以这里就把b1 的地址转换成指针的指针
//p[0];// p[0] 就是图 vbptr,指向vbtl
cout<<p[0][0]<<endl;//0
cout<<p[0][1]<<endl;//8
//打印结果与图相同 符合预期
cout<<"====="<<endl;
DD dd;
cout<<&dd<<endl;
cout<<&dd.bb_<<endl;
cout<<&dd.b1_<<endl;
cout<<&dd.b2_<<endl;
cout<<&dd.dd_<<endl;
p=(long**)ⅆ
cout<<p[0][0]<<endl;
cout<<p[0][1]<<endl;
cout<<p[2][0]<<endl;
cout<<p[2][1]<<endl;
return 0;
}
打印结构0 20 0 12 符合预期
virtual 实质上的,事实上的,存在,共享,间接。基类对象放在最后的位置。
编译时刻已经决定了内存模型。
BB* pp;
pp=&d;
pp->bb_;//通过简介访问,这需要运行时支持。
通常都将虚基类部分成员 放在类对象的末尾。如果虚基类指针指向派生类对象, 运行时会调正基类指针的地址。到虚基类表中寻找偏移地址。需要运行时支持。