C++ 对象内存布局 (2)
转载 http://blog.csdn.net/pathuang68/article/details/4101981
5
内容概要:
满足下面2个条件时,
1. 父类有虚函数,子类也有虚函数,且子类的虚函数重写或覆盖了父类的虚函数
2. 非虚继承
类对象之内存布局
在前面的例子中,恢复原来的两个虚函数vfBase_1()和vfBase_2(),同时在Derived类中重写基类的虚函数vfBase_1(),Base类和Derived类之间的关系如下图:
1 #include <iostream> 2 3 using namespace std; 4 5 6 7 class Base 8 9 { 10 11 public: 12 13 int m_base; 14 15 16 17 inline virtual void vfBase_1() 18 19 { 20 21 cout << "This is in Base::vfBase_1()" << endl; 22 23 } 24 25 26 27 inline virtual void vfBase_2() 28 29 { 30 31 cout << "This is in Base::vfBase_2()" << endl; 32 33 } 34 35 }; 36 37 38 39 class Derived : public Base 40 41 { 42 43 public: 44 45 int m_derived; 46 47 48 49 inline virtual void vfDerived() 50 51 { 52 53 cout << "This is in Derived::vfDerived()" << endl; 54 55 } 56 57 58 59 inline void vfBase_1() 60 61 { 62 63 cout << "This is in Derived::vfBase_1()" << endl; 64 65 } 66 67 }; 68 69
Derived 对象的memory layout图解如下:
因为Derived类中重写了虚函数vfBase_1(),所以Derived::vfBase_1()就取代了Base::vfBase_1()的位置,位于虚函数表的开始处。而Base::vfBase_1()就不会再在Derived的虚函数表中出现了。
5
内容概要:
满足下面3个条件时,
1. 父类有虚函数,子类也有虚函数,且子类的虚函数重写或覆盖了父类的虚函数
2. 非虚继承
3. 多重继承
类对象之内存布局
多重继承,派生类不重写基类中的虚函数。
假定各类之间的关系如下图:
1 #include <iostream> 2 3 using namespace std; 4 5 6 7 class Base1 8 9 { 10 11 public: 12 13 int m_base1; 14 15 inline virtual void vfBase1_1() 16 17 { 18 19 cout << "This is in Base1::vfBase1_1()" << endl; 20 21 } 22 23 24 25 inline virtual void vfBase1_2() 26 27 { 28 29 cout << "This is in Base1::vfBase1_2()" << endl; 30 31 } 32 33 }; 34 35 36 37 class Base2 38 39 { 40 41 public: 42 43 int m_base2; 44 45 46 47 inline virtual void vfBase2_1() 48 49 { 50 51 cout << "This is in Base2::vfBase2_1()" << endl; 52 53 } 54 55 56 57 inline virtual void vfBase2_2() 58 59 { 60 61 cout << "This is in Base2::vfBase2_2()" << endl; 62 63 } 64 65 }; 66 67 68 69 class Base3 70 71 { 72 73 public: 74 75 int m_Base3; 76 77 78 79 inline virtual void vfBase3_1() 80 81 { 82 83 cout << "This is in Base3::vfBase3_1()" << endl; 84 85 } 86 87 88 89 inline virtual void vfBase3_2() 90 91 { 92 93 cout << "This is in Base3::vfBase3_2()" << endl; 94 95 } 96 97 }; 98 99 100 101 class Derived : public Base1, public Base2, public Base3 102 103 { 104 105 public: 106 107 int m_derived; 108 109 110 111 inline virtual void fd() 112 113 { 114 115 cout << "This is in Derived::fd()" << endl; 116 117 } 118 119 };
Derived对象之memory layout如下:
由上面的分析可知:
其一:有三个虚函数表
其二:在Derived类中定义的虚函数Derived::vfDerived()附加在一个虚函数表的最后
如果在5的代码中,将Base1中的两个虚函数声明删除,同时将main函数中的下面代码注释掉(因为现在只有两张虚函数表了):
Derived对象的memory layout图解如下:
由上面分析可知:
其一,Base1 subobject排列在Base2 subobject和Base3 subobject之后,尽管它在Derived类的继承列表中排列在首位,因为它已经没有虚函数表了,但仍然排列在Derived类的成员变量m_derived之前。
其二,在Derived类中定义的虚函数Derived::vfDerived()附加在一个虚函数表的最后,这时第一张虚函数表是类Base2的。
在对象内存布局 (5)的代码中,在Derived类中覆盖Base1中声明的vfBase1_1(),其他代码不变。修改后的Derived的定义如下:
1 class Derived : public Base1, public Base2, public Base3 2 3 { 4 5 public: 6 7 int m_derived; 8 9 10 11 inline virtual void fd() 12 13 { 14 15 cout << "This is in Derived::fd()" << endl; 16 17 } 18 19 20 21 inline void vfBase1_1() 22 23 { 24 25 cout << "This is in Derived::vfBase1_1()" << endl; 26 27 } 28 29 };
Derived对象值memory layout图解如下:
我们可以看到,在Derived中overriden的虚函数Derived::vfBase1_1排在第一个虚函数表的第一位。虚函数Base::vfBase1_1()由于已经被overridden,所以在Derived对象的虚函数表中不再出现。
在内存对象布局 (5)的代码中,在Derived类中将三个基类中的虚函数分别覆盖一个,即分别覆盖Base1中声明的vfBase1_1(),Base2中声明的vfBase2_1()以及Base3中声明的vfBase3_1()。保持其他代码不变,修改后的Derived代码如下:
1 class Derived : public Base1, public Base2, public Base3 2 3 { 4 5 public: 6 7 int m_derived; 8 9 inline virtual void fd() 10 11 { 12 13 cout << "This is in Derived::fd()" << endl; 14 15 } 16 17 inline void vfBase1_1() 18 19 { 20 21 cout << "This is in Derived::vfBase1_1()" << endl; 22 23 } 24 25 inline void vfBase2_1() 26 27 { 28 29 cout << "This is in Derived::vfBase2_1()" << endl; 30 31 } 32 33 inline void vfBase3_1() 34 35 { 36 37 cout << "This is in Derived::vfBase3_1()" << endl; 38 39 } 40 41 };
Derived对象的memory layout图解如下:
Derived中覆盖的虚函数,分别出现在三个不同的虚函数表中,而且分别代替个基类的原虚函数的位置,即:
第一个虚函数表中,Derived::vfBase1_1()代替了Base::vfBase1_1()的位置,Base::vfBase1_1()不再在虚函数表中出现;
第二个虚函数表中,Derived::vfBase2_1()代替了Base::vfBase2_1()的位置,Base::vfBase2_1()不再在虚函数表中出现;
第三个虚函数表中,Derived::vfBase3_1()代替了Base::vfBase3_1()的位置,Base::vfBase3_1()不再在虚函数表中出现;
在Derived中自己定义的虚函数,总是处在第一个虚函数表的最后一项的位置。
浙公网安备 33010602011771号