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

1.虚函数

一般类的布局

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 单个虚函数

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 多个虚函数

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 不加函数

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父类的函数

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 子类添加虚函数

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 多继承

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 只在父类

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

子类实现

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 父类子类都有

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 虚继承

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 没有用虚继承

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 加上虚继承之后

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 一般结合

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 子类中有虚函数

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重写了,则

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 继承的两个父类继承自同一个祖父类

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 继承的两个父类继承自同一个祖父类并且都有虚函数

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值