c++多态对象模型:菱形继承和菱形虚拟继承

    -

一:菱形继承

class A
{
public:
    virtual void func1()
    {
        cout << "A::func1()";
    }

    virtual void func2()
    {
        cout << "A::func2()";
    }
public://这里为public,方便待会赋值查看内存
    int _a;
};

class B : public A
{
public:
    virtual void func1()
    {
        cout << "B::func1()";
    }

    virtual void func3()
    {
        cout << "B::func3()";
    }
public:
    int _b;
};

class C : public A
{
public:
    virtual void func1()
    {
        cout << "C::func1()";
    }

    virtual void func3()
    {
        cout << "C::func3()";
    }
public:
    int _c;
};

class D : public B, public C
{
public:
    virtual void func1()
    {
        cout << "D::func1()";
    }

    virtual void func4()
    {
        cout << "D::func4()";
    }
public:
    int _d;
};

它的结构是这样的:
这里写图片描述
来看他的布局:

void test()
{
    D d;
    d.B::_a = 1;
    d._b = 2;
    d.C::_a = 3;
    d._c = 4;
    d._d = 5;
}

这里写图片描述
可以看出,B继承了A,B里有A的虚表,C里有A的虚表,然后D继承了B和C,那么D里有两个虚表。
这里写图片描述
接下来打印地址:
Print((int**)(((int*)&d)));//第一个虚表
这里写图片描述
可以看到,func4依然是给了第一个虚表。

注:因为清理解决方案导致地址不同,不影响。

这样得到了菱形继承的模型:
这里写图片描述

二:菱形虚拟继承

class A
{
public:
    virtual void func1()
    {
        cout << "A::func1()";
    }

    virtual void func2()
    {
        cout << "A::func2()";
    }
public:
    int _a;
};

class B : virtual public A//虚拟继承
{
public:
    virtual void func1()
    {
        cout << "B::func1()";
    }

    virtual void func3()
    {
        cout << "B::func3()";
    }
public:
    int _b;
};

class C : virtual public A//虚拟继承
{
public:
    virtual void func1()
    {
        cout << "C::func1()";
    }

    virtual void func3()
    {
        cout << "C::func3()";
    }
public:
    int _c;
};

class D : public B, public C
{
public:
    virtual void func1()
    {
        cout << "D::func1()";
    }

    virtual void func4()
    {
        cout << "D::func4()";
    }
public:
    int _d;
};

结构变化不大,就是多了虚拟继承,那么再来看看布局:

void test()
{
    D d1;
    d1.B::_a = 1;
    d1._b = 2;
    d1.C::_a = 3;
    d1._c = 4;
    d1._d = 5;
}

这里写图片描述
好像看不出来什么,好复杂的感觉。
来看内存:
这里写图片描述
因为已经对数据成员赋值,所以看的能清楚一些,蓝色框起来的三个是属于B,桔色框起来三个属于C,紫色框起来三个属于A,接下来我用到打印函数。


    Print((int**)(*((int**)&d1)));
    Print((int**)(*((int**)((char*)&d1 + 12))));
    Print((int**)(*((int**)(    (char*)&d1+28   ))));

这里写图片描述
可以看到,B的虚表存了B的func3和D的func4,C的虚表存了C的func3,A的虚表存了D的func1和A的func2。
之前有文章写了菱形继承,虚拟继承解决了二义性和数据冗余,由于D同时继承了B和C,B和C又分别继承了A,所以D里面会有两份A,所以加上虚拟继承,A会在最下面。
至于虚机表指针:

这里写图片描述
这里写图片描述
这里分别是B和C的虚机表,第一行是-4的意思,表示和虚表的地址差4字节,若没有虚表存在,就会存0。
(ff ff ff ff是-1,顺着推也能得到ff ff ff fc是-4)
第二行是距离A的步数,B离A24字节,C离A12字节。
所以得到了对象模型:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/han8040laixin/article/details/78531737