虚函数和虚继承及其在内存中布局

转自: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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值