虛函數和虛繼承及其在內存中佈局

轉自:http://blog.csdn.net/fantasywm/article/details/7828744

1.虛函數

一般類的佈局

  1. class A  
  2. {  
  3. public:  
  4.     int m_pbl;  
  5. protected:  
  6.     int m_prt;  
  7. private:  
  8.     int m_prv;  
  9. public:  
  10. voidfun() // 不在堆棧中佔空間  
  11. {  
  12.         cout << "It'sfun." << endl;  
  13.     }  
  14. };  
class A
{
public:
    int m_pbl;
protected:
    int m_prt;
private:
    int m_prv;
public:
voidfun() // 不在堆棧中佔空間
{
        cout << "It'sfun." << endl;
    }
};

 

1>  class A   size(12):

1>       +---

1>   0   |m_pbl

1>   4   |m_prt

1>   8   |m_prv

1>       +---

1.1 單個類

1.1.1 單個虛函數

  1. class A  
  2. {  
  3. public:  
  4.     int m_pbl;  
  5. protected:  
  6.     int m_prt;  
  7. private:  
  8.     int m_prv;  
  9. public:  
  10.     void virtual f1()  
  11.     {  
  12.         cout << "It'sf1." << endl;  
  13.     }  
  14. };  
class A
{
public:
    int m_pbl;
protected:
    int m_prt;
private:
    int m_prv;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};

 

2>  class A   size(16):

2>       +---

2>   0   | {vfptr} // 虛表指針

2>   4   |m_pbl

2>   8   |m_prt

2>  12   |m_prv

2>        +---

2> 

2>  A::$vftable@:// 虛表

2>       | &A_meta

2>        |  0

2>   0   |&A::f1

2> 

2>  A::f1 this adjustor: 0

1.1.2 多個虛函數

  1. class A  
  2. {  
  3. public:  
  4.     int m_pbl;  
  5. protected:  
  6.     int m_prt;  
  7. private:  
  8.     int m_prv;  
  9. public:  
  10.     void virtual f1()  
  11.     {  
  12.         cout << "It'sf1." << endl;  
  13.     }  
  14.     void virtual f2()  
  15.     {  
  16.         cout << "It'sf2." << endl;  
  17.     }  
  18. };  
class A
{
public:
    int m_pbl;
protected:
    int m_prt;
private:
    int m_prv;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
    void virtual f2()
    {
        cout << "It'sf2." << endl;
    }
};

 

1>  class A   size(16):

1>       +---

1>   0   |{vfptr}

1>   4   |m_pbl

1>   8   |m_prt

1>  12   | m_prv

1>       +---

1> 

1>  A::$vftable@: // 同一張表中

1>       | &A_meta

1>       |  0

1>   0   |&A::f1

1>   1   |&A::f2

1> 

1>  A::f1 this adjustor: 0

1>  A::f2 this adjustor: 0

1.2 繼承

1.2.1 不加函數

  1. class B : public A  
  2. {  
  3. };  
class B : public A
{
};

1>  class B   size(16):

1>  +---

1>  | +--- (baseclass A)

1>   0   | | {vfptr}//同一個指針

1>   4   | |m_pbl

1>   8   | |m_prt

1>  12   | |m_prv

1>   | +---

1>  +---

1> 

1> B::$vftable@: // B的虛表

1>  |&B_meta

1>  |  0

1>   0   |&A::f1

1>   1   |&A::f2

1.2.2 子類override父類的函數

  1. class B : public A  
  2. {  
  3. public:  
  4.     void f1()  
  5.     {  
  6.         cout << "It'sf1 in B." << endl;  
  7.     }  
  8. };  
class B : public A
{
public:
    void f1()
    {
        cout << "It'sf1 in B." << endl;
    }
};

1>  class B   size(16):

1>       +---

1>       | +--- (base class A)

1>   0   | |{vfptr}

1>   4   | |m_pbl

1>   8   | |m_prt

1>  12   | |m_prv

1>       | +---

1>       +---

1> 

1>  B::$vftable@:

1>       | &B_meta// B用來標識類

1>       |  0

1>   0   | &B::f1 // 變成了B的版本

1>   1   |&A::f2

1> 

1>  B::f1 this adjustor: 0

1.2.3 子類添加虛函數

  1. class B : public A  
  2. {  
  3. public:  
  4.     void f1()  
  5.     {  
  6.         cout << "It'sf1 in B." << endl;  
  7.     }  
  8.     void virtual f3()  
  9.     {  
  10.         cout << "It'sf3." << endl;  
  11.     }  
  12. };  
class B : public A
{
public:
    void f1()
    {
        cout << "It'sf1 in B." << endl;
    }
    void virtual f3()
    {
        cout << "It'sf3." << endl;
    }
};

1>  class B   size(16):

1>  +---

1>  | +---(base class A)

1>   0   | |{vfptr} //合成一個表

1>   4   | |m_pbl

1>   8   | |m_prt

1>  12   | |m_prv

1>  | +---

1>  +---

1> 

1>  B::$vftable@:

1>  |&B_meta

1>  |  0

1>   0   |&B::f1

1>   1   |&A::f2

1>   2   | &B::f3 // 添加到虛表的尾部,類標識爲B

1> 

1>  B::f1 this adjustor: 0

1>  B::f3 this adjustor: 0

1.2.4 多繼承

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1()  
  7.     {  
  8.         cout << "It'sf1." << endl;  
  9.     }  
  10. };  
  11. class B  
  12. {  
  13. public:  
  14.     void virtual f1()  
  15.     {  
  16.         cout << "It'sf1 in B." << endl;  
  17.     }  
  18. };  
  19. class C : public A, public B  
  20. {  
  21. };  
class A
{
private:
    int m_data;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};
class B
{
public:
    void virtual f1()
    {
        cout << "It'sf1 in B." << endl;
    }
};
class C : public A, public B
{
};

 

1>  class C   size(12):

1>        +---

1>       | +--- (base class A)

1>   0   | |{vfptr}

1>   4   | |m_data

1>       | +---

1>       | +--- (base class B)

1>   8   | | {vfptr}  // 多個指針

1>       | +---

1>       +---

1> 

1>  C::$vftable@A@:

1>  |&C_meta

1>  |  0

1>   0   |&A::f1

1> 

1>  C::$vftable@B@:

1>  | -8

1>   0   |&B::f1 

1.3 純虛函數

1.3.1 只在父類

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1() = 0;  
  7. };  
class A
{
private:
    int m_data;
public:
    void virtual f1() = 0;
};

1>  class A   size(8):

1>        +---

1>   0   |{vfptr}

1>   4   | m_data

1>       +---

1> 

1>  A::$vftable@:

1>       | &A_meta

1>       |  0

1>   0   |&A::f1

1> 

1>  A::f1 this adjustor: 0

子類實現

  1. class B : public A  
  2. {  
  3. public:  
  4.     void f1()  
  5.     {  
  6.         cout << "It'sf1 in B." << endl;  
  7.     }  
  8. };  
class B : public A
{
public:
    void f1()
    {
        cout << "It'sf1 in B." << endl;
    }
};

1>  class B   size(8):

1>       +---

1>       | +--- (base class A)

1>   0   | |{vfptr}

1>   4   | |m_data

1>       | +---

1>       +---

1> 

1>  B::$vftable@:

1>       | &B_meta

1>       |  0

1>   0   | &B::f1

1> 

1>  B::f1 this adjustor: 0 

1.3.2 父類子類都有

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1() = 0;  
  7. };  
  8. class B : public A  
  9. {  
  10. public:  
  11.     void virtual f3() = 0;  
  12. };  
class A
{
private:
    int m_data;
public:
    void virtual f1() = 0;
};
class B : public A
{
public:
    void virtual f3() = 0;
};

1>  class B   size(8):

1>       +---

1>       | +--- (base class A)

1>   0   | |{vfptr}

1>   4   | |m_data

1>       | +---

1>       +---

1> 

1>  B::$vftable@:

1>       | &B_meta

1>       |  0

1>   0   |&A::f1

1>   1   |&B::f3

1> 

1>  B::f3 this adjustor: 0

 純虛函數在內存中佈局和一般的虛函數一樣。


2.虛繼承

2.1 虛繼承

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. };  
  6. class B : virtual public A  
  7. {  
  8. };  
class A
{
private:
    int m_data;
};
class B : virtual public A
{
};

1>  class B   size(8):

1>       +---

1>   0   | {vbptr} // 指針

1>       +---

1>       +--- (virtual base A)

1>   4   |m_data

1>       +---

1> 

1>  B::$vbtable@:// 虛繼承表

1>   0   | 0

1>   1   | 4(Bd(B+0)A)

1> 

1> 

1>  vbi:       class offset o.vbptr  o.vbte fVtorDisp

1>                 A       4      0       4 0

2.2 兩個父類繼承自同一個祖父類

2.2.1 沒有用虛繼承

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. };  
  6. class B :  public A  
  7. {  
  8. };  
  9. class C :  public A  
  10. {  
  11. };  
  12. class D : public B, public C  
  13. {  
  14. };  
class A
{
private:
    int m_data;
};
class B :  public A
{
};
class C :  public A
{
};
class D : public B, public C
{
};

1>  class D   size(8):

1>       +---

1>       | +--- (base class B)

1>       | | +--- (base class A)

1>   0   | || m_data

1>       | | +---

1>       | +---

1>       | +--- (base class C)

1>       | | +--- (base class A)

1>   4   | || m_data // 兩個m_data

1>       | | +---

1>       | +---

1>       +---

2.2.2 加上虛繼承之後

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. };  
  6. class B : virtual public A  
  7. {  
  8. };  
  9. class C : virtual public A  
  10. {  
  11. };  
  12. class D : public B, public C  
  13. {  
  14. };  
class A
{
private:
    int m_data;
};
class B : virtual public A
{
};
class C : virtual public A
{
};
class D : public B, public C
{
};

1>  class D   size(12):

1>       +---

1>       | +--- (base class B)

1>   0   | |{vbptr}

1>       | +---

1>       | +--- (base class C)

1>   4   | |{vbptr} //添加了兩個虛繼承的指針

1>       | +---

1>       +---

1>        +--- (virtual base A)

1>   8   | m_data // 只有了一個m_data

1>       +---

1> 

1> D::$vbtable@B@:

1>   0   | 0

1>   1   | 8(Dd(B+0)A)

1> 

1> D::$vbtable@C@:

1>   0   | 0

1>   1   | 4(Dd(C+0)A)

1> 

1> 

1>  vbi:      class  offset o.vbptr  o.vbte fVtorDisp

1>                 A       8      0       4 0

 

3.虛函數和虛繼承結合

3.1 一般結合

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1()  
  7.     {  
  8.         cout << "It'sf1." << endl;  
  9.     }  
  10. };  
  11. class B : virtual public A  
  12. {  
  13. public:  
  14.     void f1()  
  15.     {  
  16.         cout << "It'sf1 in B." << endl;  
  17.     }  
  18. };  
class A
{
private:
    int m_data;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};
class B : virtual public A
{
public:
    void f1()
    {
        cout << "It'sf1 in B." << endl;
    }
};

1>  class B   size(12):

1>       +---

1>   0   | {vbptr} //虛繼承的指針在前

1>       +---

1>       +--- (virtual base A)

1>   4   | {vfptr} // 虛函數的指針在後

1>   8   |m_data

1>       +---

1> 

1>  B::$vbtable@:

1>   0   | 0

1>   1   | 4(Bd(B+0)A)

1> 

1>  B::$vftable@:

1>        | -4

1>   0   |&B::f1

1> 

1>  B::f1 this adjustor: 4

1> 

1>  vbi:      class  offset o.vbptr  o.vbte fVtorDisp

1>                 A       4      0       4 0

3.2 子類中有虛函數

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1()  
  7.     {  
  8.         cout << "It'sf1." << endl;  
  9.     }  
  10. };  
  11. class B : virtual public A  
  12. {  
  13. public:  
  14.     void virtual f2()  
  15.     {  
  16.         cout << "It'sf2." << endl;  
  17.     }  
  18. };  
class A
{
private:
    int m_data;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};
class B : virtual public A
{
public:
    void virtual f2()
    {
        cout << "It'sf2." << endl;
    }
};

 

class B  size(16):

1>       +---

1>   0   | {vfptr}

1>   4   | {vbptr}

1>       +---

1>       +--- (virtual base A)

1>   8   | {vfptr} // 2個指針

1>  12   |m_data

1>       +---

1> 

1> B::$vftable@B@:

1>      |&B_meta

1>      |  0

1>   0  | &B::f2

1> 

1>  B::$vbtable@:

1>   0   |-4

1>   1   | 4(Bd(B+4)A)

1> 

1> B::$vftable@A@:

1>  | -8

1>   0  | &A::f1

1> 

1>  B::f2 this adjustor: 0

1> 

1>  vbi:      class offset o.vbptr  o.vbte fVtorDisp

1>                 A       8      4       4 0

這種情況比較特殊,與不是虛繼承的類相比,子類單獨添加了一個虛表的指針。

若B對f1重寫了,則

  1. class B : virtual public A  
  2. {  
  3. public:  
  4.     void f1()  
  5.     {  
  6.         cout << "It'sf1 int B." << endl;  
  7.     }  
  8.     void virtual f2()  
  9.     {  
  10.         cout << "It'sf2." << endl;  
  11.     }  
  12. };  
class B : virtual public A
{
public:
    void f1()
    {
        cout << "It'sf1 int B." << endl;
    }
    void virtual f2()
    {
        cout << "It'sf2." << endl;
    }
};

 

1>  class B   size(16):

1>       +---

1>   0   |{vfptr}

1>   4   |{vbptr}

1>        +---

1>        +--- (virtual base A)

1>   8   |{vfptr}

1>  12   |m_data

1>       +---

1> 

1>  B::$vftable@B@:

1>       | &B_meta

1>       |  0

1>   0   |&B::f2

1> 

1>  B::$vbtable@:

1>   0   |-4

1>   1   | 4(Bd(B+4)A)

1> 

1>  B::$vftable@A@:

1>       | -8

1>   0   | &B::f1 // f1變成了B的版本

1> 

1>  B::f1 this adjustor: 8

1>  B::f2 this adjustor: 0

1> 

1>  vbi:       class offset o.vbptr  o.vbte fVtorDisp

1>                 A       8      4       4 0

3.3 繼承的兩個父類繼承自同一個祖父類

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1()  
  7.     {  
  8.         cout << "It'sf1." << endl;  
  9.     }  
  10. };  
  11. class B : virtual public A  
  12. {  
  13. };  
  14. class C : virtual public A  
  15. {  
  16. };  
  17. class D : public B, public C  
  18. {  
  19. };  
class A
{
private:
    int m_data;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};
class B : virtual public A
{
};
class C : virtual public A
{
};
class D : public B, public C
{
};

1>  class D   size(16):

1>       +---

1>       | +--- (base class B)

1>   0   | |{vbptr}

1>       | +---

1>       | +--- (base class C)

1>   4   | |{vbptr} // 不同類的不同

1>       | +---

1>        +---

1>       +--- (virtual base A)

1>   8   | {vfptr} // 只有一個

1>  12   |m_data

1>       +---

1> 

1>  D::$vbtable@B@:

1>   0   | 0

1>   1   | 8(Dd(B+0)A)

1> 

1>  D::$vbtable@C@:

1>   0   | 0

1>   1   | 4(Dd(C+0)A)

1> 

1>  D::$vftable@:

1>       | -8

1>   0   |&A::f1

1> 

1> 

1>  vbi:        class  offset o.vbptr  o.vbte fVtorDisp

1>                 A       8      0       4 0

3.4 繼承的兩個父類繼承自同一個祖父類並且都有虛函數

  1. class A  
  2. {  
  3. private:  
  4.     int m_data;  
  5. public:  
  6.     void virtual f1()  
  7.     {  
  8.         cout << "It'sf1." << endl;  
  9.     }  
  10. };  
  11. class B : virtual public A  
  12. {  
  13. public:  
  14.     void virtual f2()  
  15.     {  
  16.         cout << "It'sf2." << endl;  
  17.     }  
  18. };  
  19. class C : virtual public A  
  20. {  
  21. public:  
  22.     void virtual f3()  
  23.     {  
  24.         cout << "It'sf3." << endl;  
  25.     }  
  26. };  
  27. class D : public C, public B  
  28. {  
  29. public:  
  30.     void virtual f4()  
  31.     {  
  32.         cout << "It'sf4." << endl;  
  33.     }  
  34. };  
class A
{
private:
    int m_data;
public:
    void virtual f1()
    {
        cout << "It'sf1." << endl;
    }
};
class B : virtual public A
{
public:
    void virtual f2()
    {
        cout << "It'sf2." << endl;
    }
};
class C : virtual public A
{
public:
    void virtual f3()
    {
        cout << "It'sf3." << endl;
    }
};
class D : public C, public B
{
public:
    void virtual f4()
    {
        cout << "It'sf4." << endl;
    }
};

1>  class D   size(24):

1>       +---

1>       | +--- (base class C) // 虛繼承C

1>   0   | |{vfptr}

1>   4   | |{vbptr}

1>       | +---

1>        | +--- (base class B) // 虛繼承B

1>   8   | |{vfptr}

1>  12   | |{vbptr}

1>       | +---

1>       +---

1>        +--- (virtual base A)

1>  16   |{vfptr}

1>  20   |m_data

1>       +---

1> 

1>  D::$vftable@C@:

1>       | &D_meta

1>       |  0

1>   0   |&C::f3

1>   1   | &D::f4 // 非虛繼承則不添加虛表指針,虛函數加到第一個虛表中

1> 

1>  D::$vftable@B@:

1>       | -8

1>   0   |&B::f2

1> 

1>  D::$vbtable@C@:

1>   0   |-4

1>   1   |12 (Dd(C+4)A)

1> 

1>  D::$vbtable@B@:

1>   0   |-4

1>   1   | 4(Dd(B+4)A)

1> 

1>  D::$vftable@A@:

1>       | -16

1>   0   |&A::f1

1> 

1>  D::f4 this adjustor: 0

1> 

1>  vbi:       class offset o.vbptr  o.vbte fVtorDisp

1>                 A      16      4       4 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章