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中自己定义的虚函数,总是处在第一个虚函数表的最后一项的位置。

 

posted @ 2013-10-27 22:00  0弓虽  阅读(246)  评论(0)    收藏  举报