C++多继承虚函数类内部模型结构剖析

来源:互联网 发布:insert into 跨数据库 编辑:程序博客网 时间:2024/05/29 13:46

这里主要看看C++在多继承含有虚函数的情况下类的内部成员结构和分布。

类继承体系代码如下,先看看非虚继承的情况:

class Base{public:Base(){}virtual ~Base(){}virtual void v(){}void f(){}public:int data_Base;};class Base1 :  public Base{public:Base1(){}virtual ~Base1(){}virtual void v1(){}void f1(){}public:int data_Base1;};class Base2 :  public Base{public:Base2(){}virtual ~Base2(){}virtual void v2(){}void f2(){}public:int data_Base2;};class Derived : public Base1, public Base2 {public:Derived(){}virtual ~Derived(){}virtual void v(){}virtual void v1(){}virtual void v2(){}virtual void v3(){}void f3(){}public:int data_Derived;};

使用VS2010提供的Command Prompt工具里的"cld1"命令查看类的结构如下:


由此可以看到,Derived类在内存里由低到高地址存储的分别是:

vfptr(虚函数表指针,包含Derived类新增的虚函数以及重写的或未重写的Base1基类的虚函数);

data_Base(Base基类的成员变量);

data_Base1(Base1基类的成员变量);

vfptr(虚函数表指针,包含Derived类重写的或未重写的Base2基类的虚函数);

data_Base(Base基类的成员变量);

data_Base2(Base2基类的成员变量);

data_Derived(Derived基类的成员变量);

总共28个字节,以下是测试代码:

int main(void){Base1 base1;Derived derived;int *p1 = (int*)(&base1);int *p2 = (int*)(&derived);derived.data_Base1 = 3;derived.data_Base2 = 4;derived.Base1::data_Base = 1;derived.Base2::data_Base = 2;derived.data_Derived = 5;for (int i = 0; i < 10; i++){cout << hex <<p2<<":"<<hex<<*p2++ << endl;}cout << "derived size:" <<dec<< sizeof(derived) << endl;int a = 0;cin >> a;return 0;}

代码打印从Derived实例内存首地址开始的十个整形数据,结果如下:


与上面分析的一致,可以看出Derived包含了基类Base的两份数据,因此需要使用虚继承去掉公共基类的数据重复,加上虚继承后的类代码如下:

class Base{public:Base(){}virtual ~Base(){}virtual void v(){}void f(){}protected:float data_Base;};class Base1 : virtual  public Base{public:Base1(){}virtual ~Base1(){}virtual void v1(){}void f1(){}protected:float data_Base1;};class Base2 : virtual  public Base{public:Base2(){}virtual ~Base2(){}virtual void v2(){}void f2(){}protected:float data_Base2;};class Derived : public Base1, public Base2 {public:Derived(){}virtual ~Derived(){}virtual void v(){}virtual void v1(){}virtual void v2(){}virtual void v3(){}void f3(){}protected:float data_Derived;};

类结构分析结果如下:


由此可以看到,加上虚继承后Derived类在内存里由低到高地址存储的分别是:

vfptr(虚函数表指针,包含Derived类新增的虚函数以及重写的或为重写的Base1基类的虚函数);

vbptr(Base1基类指向公共基类成分部分的指针)

data_Base1(Base1基类的成员变量);

vfptr(虚函数表指针,包含Derived类重写的或未重写的Base2基类的虚函数);

vbptr(Base2基类指向公共基类成分部分的指针)

data_Base2(Base2基类的成员变量);

data_Derived(Derived基类的成员变量);

vtordip(C++虚继承机制历史遗留的成员,始终为0);

vbptr(虚函数表指针,包含Derived类重写的或未重写的Base基类的虚函数);

data_Base(Base公用基类的成员变量)

总共40个字节,以下是测试代码:

int main(void){Base1 base1;Derived derived;int *p1 = (int*)(&base1);int *p2 = (int*)(&derived);derived.data_Base1 = 3;derived.data_Base2 = 4;derived.data_Base = 1;derived.data_Derived = 5;for (int i = 0; i < 10; i++){cout << hex <<p2<<":"<<hex<<*p2++ << endl;}cout << "derived size:" <<dec<< sizeof(derived) << endl;int a = 0;cin >> a;return 0;}


OK,与上面分析的一致。
0 0
原创粉丝点击