C++多继承虚函数类内部模型结构剖析
2015-03-27 14:31
309 查看
这里主要看看C++在多继承含有虚函数的情况下类的内部成员结构和分布。
类继承体系代码如下,先看看非虚继承的情况:
使用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个字节,以下是测试代码:
代码打印从Derived实例内存首地址开始的十个整形数据,结果如下:
与上面分析的一致,可以看出Derived包含了基类Base的两份数据,因此需要使用虚继承去掉公共基类的数据重复,加上虚继承后的类代码如下:
类结构分析结果如下:
由此可以看到,加上虚继承后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个字节,以下是测试代码:
OK,与上面分析的一致。
类继承体系代码如下,先看看非虚继承的情况:
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,与上面分析的一致。
相关文章推荐
- C++三大特性之多态(二)---深度剖析各种虚继承虚函数以及虚表的内容存放
- 深入理解C++对象模型-成员函数的本质以及虚函数的实现(非虚继承)
- 深入剖析C++继承,多态以及隐藏(一)。(虚函数探究)
- 剖析C++5种继承模型
- 三十二、C++内存布局,对象大小计算、虚函数虚继承对类内存模型的影响
- c++中虚函数继承,虚表剖析
- C++ 无虚函数、无虚基类的继承内存模型
- 浅析C++中虚函数的调用及对象的内部布局
- 浅析C++中虚函数的调用及对象的内部布局2 (来自:lizhe1985)
- 浅析C++中虚函数的调用及对象的内部布局
- [C++对象模型][8]多重继承与虚函数表
- 浅析C++中虚函数的调用及对象的内部布局1 (来自:lizhe1985)
- [C++对象模型][7]单继承与虚函数表
- C++ 虚继承与普通继承的内存模型对比
- [C++对象模型][5]堆栈与函数调用
- 深入剖析C++继承,多态以及隐藏(三)(类层次中的转化问题)
- C++对象模型之函数成员(4)
- [转]浅析C++中虚函数的调用及对象的内部布局(利用汇编深刻理解C++虚函数底层实现机制)
- C++中包含有虚函数的单继承状态下的类的内存布局
- C++中类成员函数指针的继承