C++ 虚继承、虚函数模型

MSVC编译器下内存模型

结论:

        1、在类中存在虚函数情况下,至少有一个vfptr(虚函数指针),每虚继承一个类、产生一个vbptr(虚基类指针)

        2、没有虚继承情况下,子类中的vfptr属于子类,指向的虚函数表包含父类和子类的虚函数;在有虚继承情况下,子类中存在新的虚函数情况下(不包括override父类虚函数),父类产生一个vfptr(虚函数指针)指向的虚函数表包含归属父类的虚函数和子类重写父类的虚函数。

        3、在虚继承情况下,子类override重写父类的虚函数,该虚函数重写在父类的虚函数表中

class Base{
public:
    virtual void funcB(){}
    int aBase;
};        //    16Byte

class Derived1 :virtual public Base{
public:
    void funcB(){}
    virtual void funcD1(){}
    int aD1;
};        // 40Byte

class Derived2 :virtual public Base{
public:
    virtual void funcD2(){}
    int aD2;
};        // 40Byte

class EndDerived :virtual public Derived1,virtual public Derived2{
public:
    // virtual void funcEd(){}    // 会产生新的vfptr  88Byte
    // void funcEd(){}            // 不会产生vfptr    80Byte
    void funcD1(){}               // 不会产生vfptr    80Byte
    int aEd;
};

子类中有新虚函数情况 

class EndDerived        size(88):
        +---
 0      | {vfptr}
 8      | {vbptr}
16      | aEd
        | <alignment member> (size=4)
        +---
        +--- (virtual base Base)
24      | {vfptr}
32      | aBase
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived1)
40      | {vfptr}
48      | {vbptr}
56      | aD1
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived2)
64      | {vfptr}
72      | {vbptr}
80      | aD2
        | <alignment member> (size=4)
        +---

EndDerived::$vftable@:
        | &EndDerived_meta
        |  0
 0      | &EndDerived::funcEd

EndDerived::$vbtable@EndDerived@:
 0      | -8
 1      | 16 (EndDerivedd(EndDerived+8)Base)
 2      | 32 (EndDerivedd(EndDerived+8)Derived1)
 3      | 56 (EndDerivedd(EndDerived+8)Derived2)

EndDerived::$vftable@Base@:
        | -24
 0      | &thunk: this+=40; goto Derived1::funcB

EndDerived::$vftable@Derived1@:
        | -40
 0      | &Derived1::funcD1

EndDerived::$vbtable@Derived1@:
 0      | -8
 1      | -24 (EndDerivedd(Derived1+8)Base)

EndDerived::$vftable@Derived2@:
        | -64
 0      | &Derived2::funcD2

EndDerived::$vbtable@Derived2@:
 0      | -8
 1      | -48 (EndDerivedd(Derived2+8)Base)

 子类中重写父类虚函数,无新虚函数

class EndDerived        size(80):
        +---
 0      | {vbptr}
 8      | aEd
        | <alignment member> (size=4)
        +---
        +--- (virtual base Base)
16      | {vfptr}
24      | aBase
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived1)
32      | {vfptr}
40      | {vbptr}
48      | aD1
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived2)
56      | {vfptr}
64      | {vbptr}
72      | aD2
        | <alignment member> (size=4)
        +---

EndDerived::$vbtable@EndDerived@:
 0      | 0
 1      | 16 (EndDerivedd(EndDerived+0)Base)
 2      | 32 (EndDerivedd(EndDerived+0)Derived1)
 3      | 56 (EndDerivedd(EndDerived+0)Derived2)

EndDerived::$vftable@Base@:
        | -16
 0      | &thunk: this+=40; goto Derived1::funcB

EndDerived::$vftable@Derived1@:
        | -32
 0      | &EndDerived::funcD1        // 重写的函数在相应基类的虚函数表中

EndDerived::$vbtable@Derived1@:
 0      | -8
 1      | -24 (EndDerivedd(Derived1+8)Base)

EndDerived::$vftable@Derived2@:
        | -56
 0      | &Derived2::funcD2

EndDerived::$vbtable@Derived2@:
 0      | -8
 1      | -48 (EndDerivedd(Derived2+8)Base)

 子类中不重写父类虚函数,无新虚函数

class EndDerived        size(80):
        +---
 0      | {vbptr}
 8      | aEd
        | <alignment member> (size=4)
        +---
        +--- (virtual base Base)
16      | {vfptr}
24      | aBase
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived1)
32      | {vfptr}
40      | {vbptr}
48      | aD1
        | <alignment member> (size=4)
        +---
        +--- (virtual base Derived2)
56      | {vfptr}
64      | {vbptr}
72      | aD2
        | <alignment member> (size=4)
        +---

EndDerived::$vbtable@EndDerived@:
 0      | 0
 1      | 16 (EndDerivedd(EndDerived+0)Base)
 2      | 32 (EndDerivedd(EndDerived+0)Derived1)
 3      | 56 (EndDerivedd(EndDerived+0)Derived2)

EndDerived::$vftable@Base@:
        | -16
 0      | &thunk: this+=40; goto Derived1::funcB

EndDerived::$vftable@Derived1@:
        | -32
 0      | &Derived1::funcD1

EndDerived::$vbtable@Derived1@:
 0      | -8
 1      | -24 (EndDerivedd(Derived1+8)Base)

EndDerived::$vftable@Derived2@:
        | -56
 0      | &Derived2::funcD2

EndDerived::$vbtable@Derived2@:
 0      | -8
 1      | -48 (EndDerivedd(Derived2+8)Base)

GNU编译器下内存模型

GNU编译器下共享vfptr,共用一个虚函数表,由偏移量的不同确定函数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值