//C++对象模型
//存在虚函数与虚继承的情况
#include <iostream>
using namespace std;
typedef void (*FUNC)();
FUNC fun;
#define PRT(x) cout<<x<<endl
#define RUN(x) fun = (FUNC)x; \
fun()
class BB
{
public:
BB():bb_(0xbb)
{
}
virtual void vfbb()
{
PRT("BB::vfbb()...");
}
virtual void vfbb2()
{
PRT("BB::vfbb2()...");
}
int bb_;
};
class B1:virtual public BB
{
public:
B1():b1_(0xb1)
{
}
virtual void vfb1()
{
PRT("B1::vfb1()...");
}
int b1_;
};
class B2:virtual public BB
{
public:
B2():b2_(0xb2)
{
}
virtual void vfb2()
{
PRT("B2::vfb2()...");
}
int b2_;
};
class DD:public B1, public B2
{
public:
DD():dd_(0xdd)
{
}
virtual void vfdd()
{
PRT("DD::vfdd()...");
}
int dd_;
};
int main()
{
long** p;
PRT(sizeof(BB));//8
PRT(sizeof(B1));//20
PRT(sizeof(B2));//20
PRT(sizeof(DD));//36
PRT("------BB------");
BB bb;
//PRT(&bb);
//PRT(&bb.bb_);
p = (long**)&bb;
RUN(p[0][0]); //BB::vfbb()
RUN(p[0][1]); //BB::vfbb2()
PRT("------B1------");
B1 b1;
//PRT(&b1);
//PRT(&b1.b1_);
//PRT(&b1.bb_);
p = (long**)&b1;
RUN(p[0][0]); //B1::vfb1()
PRT(p[1][0]); //-4
PRT(p[1][1]); //8
PRT(p[2]);
RUN(p[3][0]); //BB::vfbb()
RUN(p[3][1]); //BB::vfbb2()
PRT(p[4]);
PRT("------DD------");
DD dd;
//PRT(&dd);
//PRT(&dd.b1_);
//PRT(&dd.b2_);
//PRT(&dd.dd_);
//PRT(&dd.bb_);
p = (long**)ⅆ
RUN(p[0][0]); //B1::vfb1()
RUN(p[0][1]); //DD::vfdd()
PRT(p[1][0]); //-4
PRT(p[1][1]); //24
PRT(p[2]);
RUN(p[3][0]); //B2::vfb2()
PRT(p[4][0]); //-4
PRT(p[4][1]); //12
PRT(p[5]);
PRT(p[6]);
RUN(p[7][0]); //BB::vfbb()
RUN(p[7][1]); //BB::vfbb2()
PRT(p[8]);
return 0;
}
/*
内存模型
BB
+---------+虚表指针指向虚表 vtbl
| vptr |--------------->+-----------+
+---------+ |BB::vfbb() |虚函数入口地址
| bb_ | +-----------+
+---------+ |BB::vfbb2()|
+-----------+
B1
+---------+ 虚表指针指向虚表 vtbl
| vptr |------------------------------->+-----------+
+---------+ |B1::vfb1() |
| vbptr |---+虚基类表指针指向虚基类表 +-----------+
+---------+ | vbtl
| b1_ | +-->+---------+
+---------+ | -4 |本类地址与虚基类表指针地址的差,如果没有虚函数(虚表)则为0
| vptr |---+ +---------+
+---------+ | | 8 |虚基类地址与虚基类表指针地址的差
| bb_ | | +---------+ vtbl
+---------+ +--------------------------->+-----------+
虚表指针指向虚表 |BB::vfbb() |
如果是非虚继承则B1中的两个虚表将合并为一个 +-----------+
|BB::vfbb2()|
+-----------+
DD
+---------+ vtbl
| vptr |------------------------------->+-----------+
+---------+ vbtl |B1::vfb1() |
| vbptr |------------->+----------+ +-----------+
+---------+ | -4 | |DD::vfdd() |
| b1_ | +----------+ +-----------+
+---------+ | 24 |
| vptr |----------+ +----------+ vtbl
+---------+ +-------------------->+-----------+
| vbptr |-------+ vbtl |B2::vfb2() |
+---------+ +----->+----------+ +-----------+
| b2_ | | -4 |
+---------+ +----------+
| dd_ | | 12 |
+---------+ +----------+ vtbl
| vptr |------------------------------->+-----------+
+---------+ |BB::vfbb() |
| bb_ | +-----------+
+---------+ |BB::vfbb2()|
+-----------+
*/
C++对象模型(存在虚函数与虚继承的情况)
最新推荐文章于 2021-07-30 15:58:36 发布